我的 json 序列化有一些問題,我使用json_serializable: ^6.2.0,所以我的代碼是:
shift.dart:
import 'package:hive/hive.dart';
import 'package:json_annotation/json_annotation.dart';
part 'shift.g.dart';
@HiveType(typeId: 1)
@JsonSerializable()
class Shift extends HiveObject {
@HiveField(0)
final DateTime? start;
@HiveField(1)
final DateTime? end;
@HiveField(2, defaultValue: Duration(hours: 8))
final Duration? duration;
Shift({required this.start, required this.end, Duration? duration})
: duration = duration ?? const Duration(hours: 8);
Shift copyWith({
DateTime? start,
DateTime? end,
Duration? duration,
}) {
return Shift(
start: start ?? this.start,
end: end ?? this.end,
duration: duration ?? this.duration,
);
}
Map<String, dynamic> toJson() => _$ShiftToJson(this);
factory Shift.fromJson(Map<String, dynamic> json) => _$ShiftFromJson(json);
// Equatable does not work with HiveObjects, necessary to override hashCode ==
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is Shift &&
runtimeType == other.runtimeType &&
start == other.start &&
end == other.end &&
duration == other.duration;
@override
int get hashCode => start.hashCode ^ end.hashCode ^ duration.hashCode;
}
shift.g.dart:
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'shift.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class ShiftAdapter extends TypeAdapter<Shift> {
@override
final int typeId = 1;
@override
Shift read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i ) reader.readByte(): reader.read(),
};
return Shift(
start: fields[0] as DateTime?,
end: fields[1] as DateTime?,
duration:
fields[2] == null ? const Duration(hours: 8) : fields[2] as Duration?,
);
}
@override
void write(BinaryWriter writer, Shift obj) {
writer
..writeByte(3)
..writeByte(0)
..write(obj.start)
..writeByte(1)
..write(obj.end)
..writeByte(2)
..write(obj.duration);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is ShiftAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
Shift _$ShiftFromJson(Map<String, dynamic> json) => Shift(
start: json['start'] == null
? null
: DateTime.parse(json['start'] as String),
end: json['end'] == null ? null : DateTime.parse(json['end'] as String),
duration: json['duration'] == null
? null
: Duration(microseconds: json['duration'] as int),
);
Map<String, dynamic> _$ShiftToJson(Shift instance) => <String, dynamic>{
'start': instance.start?.toIso8601String(),
'end': instance.end?.toIso8601String(),
'duration': instance.duration?.inMicroseconds,
};
shift_cubit.dart:
import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:timer/cubit/shift/shift_state.dart';
import '../../model/shift.dart';
class ShiftCubit extends HydratedCubit<ShiftState> {
ShiftCubit()
: super(
ShiftState(
shift: Shift(
start: null,
end: null,
duration: const Duration(hours: 8),
),
enabledStart: true,
enabledEnd: false,
status: ShiftStateStatus.initial,
),
);
void updateStart(DateTime start) {
emit(
ShiftState(
shift: Shift(
start: start,
end: null,
duration: const Duration(hours: 8),
),
enabledStart: false,
enabledEnd: true,
status: ShiftStateStatus.startTapped,
),
);
}
void updateEnd(DateTime end) {
emit(
ShiftState(
shift: Shift(
start: state.shift.start,
end: end,
duration: const Duration(hours: 8),
),
enabledStart: false,
enabledEnd: false,
status: ShiftStateStatus.endTapped,
),
);
}
void resetNewDay() {
emit(
ShiftState(
shift: Shift(
start: null,
end: null,
duration: const Duration(hours: 8),
),
enabledStart: true,
enabledEnd: false,
status: ShiftStateStatus.initial,
),
);
}
@override
ShiftState fromJson(Map<String, dynamic> json) {
return ShiftState.fromJson(json);
}
@override
Map<String, dynamic> toJson(ShiftState state) {
return state.toJson();
}
}
shift_state.dart:
import 'dart:convert';
import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart';
import '../../model/shift.dart';
part 'shift_state.g.dart';
enum ShiftStateStatus { initial, startTapped, endTapped }
@JsonSerializable()
class ShiftState extends Equatable {
final Shift shift;
final bool enabledStart;
final bool enabledEnd;
final ShiftStateStatus status;
const ShiftState({
required this.shift,
required this.enabledStart,
required this.enabledEnd,
required this.status,
});
@override
List<Object> get props => [shift, enabledStart, enabledEnd, status];
Map<String, dynamic> toJson() => _$ShiftStateToJson(this);
factory ShiftState.fromJson(Map<String, dynamic> json) =>
_$ShiftStateFromJson(json);
}
shift_state.g.dart:
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'shift_state.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
ShiftState _$ShiftStateFromJson(Map<String, dynamic> json) => ShiftState(
shift: Shift.fromJson(json['shift'] as Map<String, dynamic>),
enabledStart: json['enabledStart'] as bool,
enabledEnd: json['enabledEnd'] as bool,
status: $enumDecode(_$ShiftStateStatusEnumMap, json['status']),
);
Map<String, dynamic> _$ShiftStateToJson(ShiftState instance) =>
<String, dynamic>{
'shift': instance.shift,
'enabledStart': instance.enabledStart,
'enabledEnd': instance.enabledEnd,
'status': _$ShiftStateStatusEnumMap[instance.status],
};
const _$ShiftStateStatusEnumMap = {
ShiftStateStatus.initial: 'initial',
ShiftStateStatus.startTapped: 'startTapped',
ShiftStateStatus.endTapped: 'endTapped',
};
我嘗試測驗我的代碼,例如:
group('toJson/fromJson', () {
test('work properly', () async {
await mockHydratedStorage(() {
final shiftCubit = ShiftCubit();
expect(
shiftCubit.fromJson(shiftCubit.toJson(shiftCubit.state)),
shiftCubit.state,
);
});
});
});
結果是:type 'Shift' is not a subtype of type 'Map<String, dynamic>' in type cast
應用程式似乎運行良好,但我想知道為什么這個序列化不起作用。
編輯:
堆疊跟蹤:
package:timer/cubit/shift/shift_state.g.dart 10:43 _$ShiftStateFromJson
package:timer/cubit/shift/shift_state.dart 32:7 new ShiftState.fromJson
package:timer/cubit/shift/shift_cubit.dart 68:23 ShiftCubit.fromJson
test\bloc\bloc_test.dart 40:24 main.<fn>.<fn>.<fn>.<fn>
package:hydrated_bloc/src/hydrated_bloc.dart 62:22 HydratedBlocOverrides.runZoned.<fn>.<fn>
type 'Shift' is not a subtype of type 'Map<String, dynamic>' in type cast
uj5u.com熱心網友回復:
問題發生在shift_state.g.dart:
ShiftState _$ShiftStateFromJson(Map<String, dynamic> json) => ShiftState(
shift: Shift.fromJson(json['shift'] as Map<String, dynamic>),
enabledStart: json['enabledStart'] as bool,
enabledEnd: json['enabledEnd'] as bool,
status: $enumDecode(_$ShiftStateStatusEnumMap, json['status']),
);
Map<String, dynamic> _$ShiftStateToJson(ShiftState instance) =>
<String, dynamic>{
'shift': instance.shift,
'enabledStart': instance.enabledStart,
'enabledEnd': instance.enabledEnd,
'status': _$ShiftStateStatusEnumMap[instance.status],
};
請注意,您的toJson方法正在填充鍵為'shift'with的值instance.shift,但您fromJson期望的是Map,而不是型別的實體物件Shift。修復很簡單,您需要設定explicitToJson為 true ,例如:
@JsonSerializable(explicitToJson: true)
class ShiftState extends Equatable {
來自檔案的注釋:
{bool? explicitToJson}
If true, generated toJson methods will explicitly call toJson on nested objects.
When using JSON encoding support in dart:convert, toJson is automatically called on objects, so the default behavior (explicitToJson: false) is to omit the toJson call.
請注意,這正是我們想要的,我們希望toJson在您的情況下呼叫嵌套物件。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/479972.html
