Home > Mobile >  Json serialization does not include embedded member
Json serialization does not include embedded member

Time:08-29

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.

  • Related