@@ -24,14 +24,38 @@ KeyConfig jsonKeyForField(FieldElement2 field, ClassConfig classAnnotation) =>
2424 );
2525
2626KeyConfig _from (FieldElement2 element, ClassConfig classAnnotation) {
27- // If an annotation exists on `element` the source is a 'real' field.
28- // If the result is `null`, check the getter – it is a property.
29- // TODO: setters: github.com/google/json_serializable.dart/issues/24
3027 final obj = jsonKeyAnnotation (element);
28+ final ctorParam = classAnnotation.ctorParams
29+ .where ((e) => e.name3 == element.name3)
30+ .singleOrNull;
31+ final ctorObj = ctorParam == null
32+ ? null
33+ : jsonKeyAnnotationForCtorParam (ctorParam);
34+
35+ ConstantReader fallbackObjRead (String field) {
36+ if (ctorObj != null && ! ctorObj.isNull) {
37+ final ctorReadResult = ctorObj.read (field);
38+ if (! ctorReadResult.isNull) {
39+ if (! obj.isNull && ! obj.read (field).isNull) {
40+ log.warning (
41+ 'Field `${element .name3 }` has conflicting `JsonKey.$field ` '
42+ 'annotations: both constructor parameter and class field have '
43+ 'this annotation. Using constructor parameter value.' ,
44+ );
45+ }
46+
47+ return ctorReadResult;
48+ }
49+ }
50+ if (obj.isNull) {
51+ return ConstantReader (null );
52+ }
53+ return obj.read (field);
54+ }
3155
32- final ctorParamDefault = classAnnotation.ctorParamDefaults[element.name3] ;
56+ final ctorParamDefault = ctorParam ? .defaultValueCode ;
3357
34- if (obj.isNull) {
58+ if (obj.isNull && (ctorObj == null || ctorObj.isNull) ) {
3559 return _populateJsonKey (
3660 classAnnotation,
3761 element,
@@ -121,7 +145,7 @@ KeyConfig _from(FieldElement2 element, ClassConfig classAnnotation) {
121145 /// either the annotated field is not an `enum` or `List` or if the value in
122146 /// [fieldName] is not an `enum` value.
123147 String ? createAnnotationValue (String fieldName, {bool mustBeEnum = false }) {
124- final annotationValue = obj. read (fieldName);
148+ final annotationValue = fallbackObjRead (fieldName);
125149
126150 if (annotationValue.isNull) {
127151 return null ;
@@ -228,16 +252,17 @@ KeyConfig _from(FieldElement2 element, ClassConfig classAnnotation) {
228252 }
229253
230254 String ? readValueFunctionName;
231- final readValue = obj. read ('readValue' );
255+ final readValue = fallbackObjRead ('readValue' );
232256 if (! readValue.isNull) {
233257 readValueFunctionName = readValue.objectValue
234258 .toFunctionValue2 ()!
235259 .qualifiedName;
236260 }
237261
238- final ignore = obj.read ('ignore' ).literalValue as bool ? ;
239- var includeFromJson = obj.read ('includeFromJson' ).literalValue as bool ? ;
240- var includeToJson = obj.read ('includeToJson' ).literalValue as bool ? ;
262+ final ignore = fallbackObjRead ('ignore' ).literalValue as bool ? ;
263+ var includeFromJson =
264+ fallbackObjRead ('includeFromJson' ).literalValue as bool ? ;
265+ var includeToJson = fallbackObjRead ('includeToJson' ).literalValue as bool ? ;
241266
242267 if (ignore != null ) {
243268 if (includeFromJson != null ) {
@@ -262,11 +287,12 @@ KeyConfig _from(FieldElement2 element, ClassConfig classAnnotation) {
262287 classAnnotation,
263288 element,
264289 defaultValue: defaultValue ?? ctorParamDefault,
265- disallowNullValue: obj.read ('disallowNullValue' ).literalValue as bool ? ,
266- includeIfNull: obj.read ('includeIfNull' ).literalValue as bool ? ,
267- name: obj.read ('name' ).literalValue as String ? ,
290+ disallowNullValue:
291+ fallbackObjRead ('disallowNullValue' ).literalValue as bool ? ,
292+ includeIfNull: fallbackObjRead ('includeIfNull' ).literalValue as bool ? ,
293+ name: fallbackObjRead ('name' ).literalValue as String ? ,
268294 readValueFunctionName: readValueFunctionName,
269- required : obj. read ('required' ).literalValue as bool ? ,
295+ required : fallbackObjRead ('required' ).literalValue as bool ? ,
270296 unknownEnumValue: createAnnotationValue (
271297 'unknownEnumValue' ,
272298 mustBeEnum: true ,
0 commit comments