@@ -29,41 +29,64 @@ final public static function from(mixed $value): static
2929
3030 /** @var ClassContext<static> $context */
3131 $ context = ClassContext::getInstance (new ReflectionClass (static ::class));
32- $ instance = $ context ->newInstanceWithoutConstructor ();
3332
34- foreach ($ context ->properties as $ propertyContext ) {
35- $ serializers = $ propertyContext ->serializers ();
33+ return $ context ->hasComputedProperties
34+ ? static ::instanceWithConstructorCallFrom ($ context , $ value )
35+ : static ::instanceWithoutConstructorFrom ($ context , $ value );
36+ } catch (Throwable $ e ) {
37+ throw new DeserializeException ($ e ->getMessage (), $ e ->getCode (), $ e );
38+ }
39+ }
3640
37- if (!$ serializers ) {
38- throw new DeserializeException (
39- code: DeserializeException::NO_SERIALIZERS_ERROR_CODE
40- );
41- }
41+ /**
42+ * @param ClassContext<static> $context
43+ * @param array<string, mixed> $value
44+ *
45+ * @throws Throwable
46+ */
47+ protected static function instanceWithoutConstructorFrom (ClassContext $ context , array $ value ): static
48+ {
49+ $ instance = $ context ->newInstanceWithoutConstructor ();
4250
43- $ propertyName = $ propertyContext ->propertyName ;
44- $ propertyDeserialized = false ;
45- foreach ($ serializers as $ serializer ) {
46- try {
47- $ propertyValue = $ serializer ->deserialize ($ propertyContext , $ value );
51+ foreach ($ context ->properties as $ propertyContext ) {
52+ $ propertyName = $ propertyContext ->propertyName ;
4853
49- $ instance ->{$ propertyName } = $ propertyValue ;
54+ $ instance ->{$ propertyName } = $ propertyContext ->deserializeFrom ($ value );
55+ }
5056
51- $ propertyDeserialized = true ;
57+ return $ instance ;
58+ }
5259
53- break ;
54- } catch (DeserializeException ) {
55- }
56- }
60+ /**
61+ * @param ClassContext<static> $context
62+ * @param array<string, mixed> $value
63+ *
64+ * @throws Throwable
65+ */
66+ protected static function instanceWithConstructorCallFrom (ClassContext $ context , array $ value ): static
67+ {
68+ /** @var array<string, mixed> $args */
69+ $ args = [];
5770
58- if (!$ propertyDeserialized ) {
59- throw new DeserializeException ("Could not deserialize value for property: $ propertyName " );
60- }
71+ foreach ($ context ->constructorParams as $ paramName ) {
72+ $ propertyContext = $ context ->properties [$ paramName ] ?? null ;
73+
74+ if (!$ propertyContext ) {
75+ throw new DeserializeException (
76+ "Could not find property context for constructor param: $ paramName "
77+ );
6178 }
6279
63- return $ instance ;
64- } catch (Throwable $ e ) {
65- throw new DeserializeException ($ e ->getMessage (), $ e ->getCode (), $ e );
80+ $ args [$ paramName ] = $ propertyContext ->deserializeFrom ($ value );
81+ }
82+
83+ $ instance = $ context ->newInstanceWithConstructorCall (...$ args );
84+
85+ if (!$ instance instanceof static) {
86+ throw new DeserializeException ('Could not create instance of ' . static ::class);
6687 }
88+
89+ return $ instance ;
6790 }
6891
6992 /**
@@ -77,36 +100,14 @@ final public function jsonSerialize(): array
77100 $ context = ClassContext::getInstance (new ReflectionClass ($ this ));
78101
79102 $ serializableArray = [];
80-
81103 foreach ($ context ->properties as $ propertyContext ) {
82- $ serializers = $ propertyContext ->serializers ();
83-
84- if (!$ serializers ) {
85- throw new SerializeException (
86- code: SerializeException::NO_SERIALIZERS_ERROR_CODE
87- );
104+ if ($ propertyContext ->isComputed ) {
105+ continue ;
88106 }
89107
90108 $ propertyName = $ propertyContext ->propertyName ;
91- $ propertySerialized = false ;
92- foreach ($ serializers as $ serializer ) {
93- try {
94- $ propertyValue = $ serializer ->serialize ($ propertyContext , $ this );
95-
96- $ serializableArray [$ propertyName ] = $ propertyValue [$ propertyName ];
97109
98- $ propertySerialized = true ;
99-
100- break ;
101- } catch (SerializeException ) {
102- }
103- }
104-
105- if (!$ propertySerialized ) {
106- throw new SerializeException (
107- "Could not serialize property: $ propertyName " ,
108- );
109- }
110+ $ serializableArray [$ propertyName ] = $ propertyContext ->serializeFrom ($ this )[$ propertyName ];
110111 }
111112
112113 return $ serializableArray ;
0 commit comments