Json serialization does not include embedded member despite the use of @JsonSerializable(explicitToJson: true)
.
The member capacity
is there, but failureState
is not part of the json.
What am I missing?
part 'batteryFailureState.g.dart';
/// The live battery data
@JsonSerializable(explicitToJson: true)
class BatteryFailureState {
// Byte 0
bool? cellVoltageIsTooHighLevel1;
bool? cellVoltageIsTooHighLevel2;
/// Default constructor as required by jaon serializer
BatteryFailureState();
/// The factory constructor fro JSON
factory BatteryFailureState.fromJson(Map<String, dynamic> json) =>
_$BatteryFailureStateFromJson(json);
/// `toJson` serialisation
Map<String, dynamic> toJson() => _$BatteryFailureStateToJson(this);
}
import 'batteryFailureState.dart';
part 'batteryData.g.dart';
/// The live battery data
@JsonSerializable(explicitToJson: true)
class BatteryData {
/// Current capacity in A.h
double? capacity; // A.h
/// Battery failure state
final failureState = BatteryFailureState();
/// Default constructor as required by jaon serializer
BatteryData();
/// The factory constructor fro JSON
factory BatteryData.fromJson(Map<String, dynamic> json) =>
_$BatteryDataFromJson(json);
/// `toJson` serialisation
Map<String, dynamic> toJson() => _$BatteryDataToJson(this);
}
CodePudding user response:
It seems that the code generation is getting tripped up by a field that is final
and also can't be passed into the default constructor.
For example if you refactor so that failureState
can be passed into the constructor:
import 'package:json_annotation/json_annotation.dart';
import 'batteryFailureState.dart';
part 'batteryData.g.dart';
/// The live battery data
@JsonSerializable(explicitToJson: true)
class BatteryData {
/// Current capacity in A.h
double? capacity; // A.h
/// Battery failure state
final BatteryFailureState? failureState;
/// Default constructor as required by jaon serializer
BatteryData({this.capacity, this.failureState});
/// The factory constructor fro JSON
factory BatteryData.fromJson(Map<String, dynamic> json) =>
_$BatteryDataFromJson(json);
/// `toJson` serialisation
Map<String, dynamic> toJson() => _$BatteryDataToJson(this);
}
The generated output is:
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'batteryData.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
BatteryData _$BatteryDataFromJson(Map<String, dynamic> json) => BatteryData(
capacity: (json['capacity'] as num?)?.toDouble(),
failureState: json['failureState'] == null
? null
: BatteryFailureState.fromJson(
json['failureState'] as Map<String, dynamic>),
);
Map<String, dynamic> _$BatteryDataToJson(BatteryData instance) =>
<String, dynamic>{
'capacity': instance.capacity,
'failureState': instance.failureState?.toJson(),
};
Notice that _$BatteryDataFromJson
passes in a value for failureState
at the constructor.
However, if you refactor instead to remove final
, but don't accept it as a constructor parameter like so:
import 'package:json_annotation/json_annotation.dart';
import 'batteryFailureState.dart';
part 'batteryData.g.dart';
/// The live battery data
@JsonSerializable(explicitToJson: true)
class BatteryData {
/// Current capacity in A.h
double? capacity; // A.h
/// Battery failure state
BatteryFailureState? failureState = BatteryFailureState();
/// Default constructor as required by jaon serializer
BatteryData();
/// The factory constructor fro JSON
factory BatteryData.fromJson(Map<String, dynamic> json) =>
_$BatteryDataFromJson(json);
/// `toJson` serialisation
Map<String, dynamic> toJson() => _$BatteryDataToJson(this);
}
Now the generated output looks like this:
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'batteryData.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
BatteryData _$BatteryDataFromJson(Map<String, dynamic> json) => BatteryData()
..capacity = (json['capacity'] as num?)?.toDouble()
..failureState = json['failureState'] == null
? null
: BatteryFailureState.fromJson(
json['failureState'] as Map<String, dynamic>);
Map<String, dynamic> _$BatteryDataToJson(BatteryData instance) =>
<String, dynamic>{
'capacity': instance.capacity,
'failureState': instance.failureState?.toJson(),
};
Notice that instead of failureState
being passed into the constructor it instead sets the value using a cascade ..faulureState =
.
In your original implementation neither of these approaches would work in the generated code and so it appears to be ignoring the field altogether.