Open murnikov opened 12 months ago
My use case calls for an object hierarchy 3 levels deep. Extremely simplified example below
import 'package:flutter/material.dart'; import 'package:dart_mappable/dart_mappable.dart'; part 'main.mapper.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { // Matryoshka granddaughter = const Matryoshka('1', 'Granddaughter', null); Matryoshka daughter = const Matryoshka(2, 'Daughter', null); Matryoshka granny = Matryoshka(3, 'Granny', {daughter.id: daughter}); print('original ${granny.toString()}'); Matryoshka clone = Matryoshka.fromJson(granny.toJson()); print('clone ${clone.toString()}'); return Scaffold( appBar: AppBar( title: const Text('Title'), ), body: const Center( child: Text('whatever'), ), ); } } @MappableClass() class Matryoshka with MatryoshkaMappable { const Matryoshka(this.id, this.name, this.children); final int id; final String name; @MappableField(hook: MappableHookNullableMap()) final Map<int, Matryoshka>? children; static const fromMap = MatryoshkaMapper.fromMap; static const fromJson = MatryoshkaMapper.fromJson; } class MappableHookNullableMap extends MappingHook { const MappableHookNullableMap(); @override Object? beforeEncode(Object? value) { if (value == null) { return null; } else if (value is Map<int, dynamic>) { return value.map((key, value) => MapEntry(key.toString(), value)); } else { return value; } } @override Object? beforeDecode(Object? value) { if (value == null) { return null; } else if (value is List<dynamic> && value.isEmpty) { return null; } else if (value is Map<String, dynamic>) { return value.map((key, value) => MapEntry(int.parse(key), value)); } else { return value; } } }
Running above code results in
Restarted application in 1 701ms. I/flutter (23960): original Matryoshka(id: 3, name: Granny, children: {2: Matryoshka(id: 2, name: Daughter, children: null)}) ════════ Exception caught by widgets library ═══════════════════════════════════ The following _ChainedMapperException was thrown building MyApp(dirty): MapperException: Failed to decode (Matryoshka).children(Map<int, Matryoshka>?).value(Matryoshka): Expected a value of type Map<String, dynamic>, but got type String. The relevant error-causing widget was MyApp When the exception was thrown, this was the stack #0 TypeCheck.checked #1 ClassMapperBase.decode #2 InterfaceMapperBase.decoder #3 ClassMapperBase.decoder #4 MapperBase.decodeValue #5 _MapperContainerBase.fromValue #6 DecodingUtil.$dec #7 _MapDecoder2._decode.<anonymous closure> #8 MapBase.map (dart:collection/maps.dart:82:28) #9 _MapDecoder2._decode #10 ResolvedType._type #11 ResolvedType.provideTo #12 TypePlus.provideTo #13 _MapDecoder2.decode #14 _MapDecoder._decode #15 ResolvedType._type #16 ResolvedType.provideTo #17 TypePlus.provideTo #18 _MapDecoder.decode #19 MapMapper.decoder #20 MapperBase.decodeValue #21 _MapperContainerBase.fromValue #22 DecodingUtil.$dec #23 Field.decode #24 DecodingData.dec #25 MatryoshkaMapper._instantiate #26 InterfaceMapperBase.decode #27 ClassMapperBase.decode #28 InterfaceMapperBase.decoder #29 ClassMapperBase.decoder #30 MapperBase.decodeValue #31 InterfaceMapperBase.decodeJson #32 MatryoshkaMapper.fromJson #33 MyApp.build #34 StatelessElement.build #35 ComponentElement.performRebuild #36 Element.rebuild #37 ComponentElement._firstBuild #38 ComponentElement.mount ... Normal element mounting (27 frames) #65 Element.inflateWidget #66 Element.updateChild #67 RenderObjectToWidgetElement._rebuild #68 RenderObjectToWidgetElement.mount #69 RenderObjectToWidgetAdapter.attachToRenderTree.<anonymous closure> #70 BuildOwner.buildScope #71 RenderObjectToWidgetAdapter.attachToRenderTree #72 WidgetsBinding.attachRootWidget #73 WidgetsBinding.scheduleAttachRootWidget.<anonymous closure> #77 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:189:12) (elided 3 frames from class _Timer and dart:async-patch)
Try using 'afterEncode' instead of 'beforeEncode' in the hook.
My use case calls for an object hierarchy 3 levels deep. Extremely simplified example below
Running above code results in