@@ -6,12 +6,12 @@ import 'package:analyzer/dart/element/element.dart';
66import 'package:build/build.dart' ;
77import 'package:source_gen/source_gen.dart' ;
88
9+ import '../type_helper.dart' ;
910import 'decode_helper.dart' ;
1011import 'encoder_helper.dart' ;
1112import 'field_helpers.dart' ;
1213import 'helper_core.dart' ;
1314import 'settings.dart' ;
14- import 'type_helper.dart' ;
1515import 'utils.dart' ;
1616
1717class GeneratorHelper extends HelperCore with EncodeHelper , DecodeHelper {
@@ -61,16 +61,17 @@ class GeneratorHelper extends HelperCore with EncodeHelper, DecodeHelper {
6161 final accessibleFields = sortedFields.fold <Map <String , FieldElement >>(
6262 < String , FieldElement > {},
6363 (map, field) {
64- if (! field.isPublic) {
64+ final jsonKey = jsonKeyFor (field);
65+ if (! field.isPublic && ! jsonKey.explicitYesFromJson) {
6566 unavailableReasons[field.name] = 'It is assigned to a private field.' ;
6667 } else if (field.getter == null ) {
6768 assert (field.setter != null );
6869 unavailableReasons[field.name] =
6970 'Setter-only properties are not supported.' ;
7071 log.warning ('Setters are ignored: ${element .name }.${field .name }' );
71- } else if (jsonKeyFor (field).ignore ) {
72+ } else if (jsonKey.explicitNoFromJson ) {
7273 unavailableReasons[field.name] =
73- 'It is assigned to an ignored field.' ;
74+ 'It is assigned to a field not meant to be used in fromJson .' ;
7475 } else {
7576 assert (! map.containsKey (field.name));
7677 map[field.name] = field;
@@ -85,28 +86,47 @@ class GeneratorHelper extends HelperCore with EncodeHelper, DecodeHelper {
8586 final createResult = createFactory (accessibleFields, unavailableReasons);
8687 yield createResult.output;
8788
88- accessibleFieldSet = accessibleFields.entries
89+ final fieldsToUse = accessibleFields.entries
8990 .where ((e) => createResult.usedFields.contains (e.key))
9091 .map ((e) => e.value)
91- .toSet ();
92+ .toList ();
93+
94+ // Need to add candidates BACK even if they are not used in the factory if
95+ // they are forced to be used for toJSON
96+ for (var candidate in sortedFields.where ((element) =>
97+ jsonKeyFor (element).explicitYesToJson &&
98+ ! fieldsToUse.contains (element))) {
99+ fieldsToUse.add (candidate);
100+ }
101+
102+ // Need the fields to maintain the original source ordering
103+ fieldsToUse.sort (
104+ (a, b) => sortedFields.indexOf (a).compareTo (sortedFields.indexOf (b)));
105+
106+ accessibleFieldSet = fieldsToUse.toSet ();
92107 }
93108
94- // Check for duplicate JSON keys due to colliding annotations.
95- // We do this now, since we have a final field list after any pruning done
96- // by `_writeCtor`.
97- accessibleFieldSet.fold (
98- < String > {},
99- (Set <String > set , fe) {
100- final jsonKey = nameAccess (fe);
101- if (! set .add (jsonKey)) {
102- throw InvalidGenerationSourceError (
103- 'More than one field has the JSON key for name "$jsonKey ".' ,
104- element: fe,
105- );
106- }
107- return set ;
108- },
109- );
109+ accessibleFieldSet
110+ ..removeWhere (
111+ (element) => jsonKeyFor (element).explicitNoToJson,
112+ )
113+
114+ // Check for duplicate JSON keys due to colliding annotations.
115+ // We do this now, since we have a final field list after any pruning done
116+ // by `_writeCtor`.
117+ ..fold (
118+ < String > {},
119+ (Set <String > set , fe) {
120+ final jsonKey = nameAccess (fe);
121+ if (! set .add (jsonKey)) {
122+ throw InvalidGenerationSourceError (
123+ 'More than one field has the JSON key for name "$jsonKey ".' ,
124+ element: fe,
125+ );
126+ }
127+ return set ;
128+ },
129+ );
110130
111131 if (config.createFieldMap) {
112132 yield createFieldMap (accessibleFieldSet);
@@ -123,3 +143,13 @@ class GeneratorHelper extends HelperCore with EncodeHelper, DecodeHelper {
123143 yield * _addedMembers;
124144 }
125145}
146+
147+ extension on KeyConfig {
148+ bool get explicitYesFromJson => includeFromJson == true ;
149+
150+ bool get explicitNoFromJson => includeFromJson == false ;
151+
152+ bool get explicitYesToJson => includeToJson == true ;
153+
154+ bool get explicitNoToJson => includeFromJson == false ;
155+ }
0 commit comments