Comments (10)
I got it working with the following Converter :
class CustomDynamicConverter implements ICustomConverter<dynamic> {
const CustomDynamicConverter() : super();
@override
dynamic fromJSON(dynamic jsonValue, [JsonProperty jsonProperty]) {
final logger = Logger();
if (jsonValue is String) {
return {"iri": jsonValue};
} else {
return jsonValue;
}
}
@override
dynamic toJSON(dynamic object, [JsonProperty jsonProperty]) {
return object;
}
}
...
converters: {
dynamic: CustomDynamicConverter()
}
I didn't implement toJson
yet, but I would be glad if it could help anyone!
Thank you for your time ! And for your awesome lib :)
from dart-json-mapper.
Thank you for your answer,
I was close to a solution so I finaly got it working with converters!
class CustomDynamicConverter implements ICustomConverter<dynamic> {
const CustomDynamicConverter() : super();
@override
dynamic fromJSON(dynamic jsonValue, [JsonProperty jsonProperty]) {
// If this is a container, return as-is
if (jsonValue is Iterable) {
return jsonValue;
}
// If this is a string like "/packagings/1"
if (jsonValue is String) {
dynamic model;
RegExp type = RegExp(r'^/([a-zA-Z\_\-]*)/');
// I made a switch because in my project I have... 74 models.
// I'll try to use convertParams to avoid having too much code.
// This would also be much more clean
switch (type.stringMatch(jsonValue as String)) {
case '/packagings/':
model = Packaging();
break;
}
model.iri = jsonValue;
return model;
}
// If jsonValue is an object {"iri": "/packagings/1"}
if (jsonValue is Map<String, dynamic>) {
// But avoiding Maps which I have for translations {fr: {}, en:{}} that would result in an error
if (!jsonValue.containsKey('iri')) {
return jsonValue;
}
// Here I'll use convertParams for type value
Type type;
RegExp modelClass = RegExp(r'^/([a-zA-Z\_\-]*)/');
switch (modelClass.stringMatch(jsonValue["iri"] as String)) {
case '/packagings/':
type = Packaging;
break;
}
final context = DeserializationContext(DeserializationOptions(), type);
return JsonMapper().deserializeObject(jsonValue, context);
}
// All my models extends Stores mixin (mobX), this way I know jsonValue is already a model instance
if (jsonValue is Store) {
return jsonValue;
}
}
// To be done
@override
dynamic toJSON(dynamic object, [JsonProperty jsonProperty]) {
return object;
}
}
In my models, everywhere I have relations with other model :
@JsonProperty(converter: CustomDynamicConverter())
Packaging packaging;
It also works with ObservableList
!
@JsonProperty(converter: CustomDynamicConverter())
ObservableList<Activity> activities;
Now I think I'll not have any other trouble!
I'll post here my definitive solution with convertParams if I get it working!
I hope this could help anyone trying to do something similar.
Thank you for your help & for you great lib!
from dart-json-mapper.
Can you please add your models code as well. It's not very obvious for me what are you trying to achieve.
from dart-json-mapper.
Sure,
Here are the models :
@jsonSerializable
class Packaging extends PackagingBase with _$Packaging {
Packaging({String iri, num weight}): super(iri: iri, weight: weight);
}
@jsonSerializable
abstract class PackagingBase with Store {
PackagingBase({
this.iri,
this.weight
});
@JsonProperty()
@observable
String iri;
@JsonProperty()
@observable
num weight;
}
@jsonSerializable
class PackagingDetail extends PackagingDetailBase with _$PackagingDetail {
PackagingDetail({String iri, Packaging packaging, String name}): super(iri: iri, packaging: packaging, name: name);
}
@jsonSerializable
abstract class PackagingDetailBase with Store {
PackagingDetailBase({
this.iri,
this.packaging,
this.name
});
@JsonProperty()
@observable
String iri;
@JsonProperty()
@observable
Packaging packaging;
@JsonProperty()
@observable
String name;
}
from dart-json-mapper.
Oh I read my initial message again and yes, what I want to do might not be clear.
I want to create a PackagingDetail
with property packaging
filled with a Packaging
, no matters if json contains only a string or complete package description.
If it contains only IRI, I want to create a Packaging with the only field iri filled with the string.
If in contains a complete Packaging, I want to fill it normally.
Hope it's more clear !
from dart-json-mapper.
Uh... It doesn't work.
I have to do the following to get a begining of a solution :
class CustomPackagingConverter implements ICustomConverter<dynamic> {
const CustomPackagingConverter() : super();
@override
dynamic fromJSON(dynamic jsonValue, [JsonProperty jsonProperty]) {
if (jsonValue is String) {
Packaging packaging = Packaging():
packaging.iri = jsonValue;
return packaging;
} else {
return jsonValue;
}
}
@override
dynamic toJSON(dynamic object, [JsonProperty jsonProperty]) {
return object;
}
}
converters: {
Packaging: CustomPackagingConverter()
}
And this will deserialize correctly with the following json :
{
"iri": "/packaging_details/1",
"packaging": "/packagings/1",
}
But now, if I want to deserialize directly this model (not as a relation but as the root model I want to deserialize), with the following json :
{
"iri": "/packagings/1"
}
It ends up with the following error :
[ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Packaging'
JsonMapper.deserialize (package:dart_json_mapper/src/mapper.dart:44:5)
Because in this case I should have used the initial converter (don't know which one, something created with reflectable maybe?).
Might you please help me fix this issue? I don't know what I should do...
Thank you
from dart-json-mapper.
To avoid root model to pass through my converter, I tried setting the converter as JsonProperty
:
@observable
@JsonProperty(converter: CustomPackagingConverter())
Packaging packaging;
So when I ask to deserialize a Packaging json directly, I have no problem:
{
"iri": "/packaging_details/1",
"packaging": {"iri": "/packagings/1"}
}
=> 👍
But now I've got an error when I'm serializing a non-string value (a embedded json). e.g:
{
"iri": "/packaging_details/1",
"packaging": {"iri": "/packagings/1"}
}
=> 👎
Unhandled Exception: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Packaging' of 'value'
from dart-json-mapper.
@k-paxian any suggestion ? :x
from dart-json-mapper.
My suggestion would be to skip converter approach and take a look at this unmapped-properties
starter code could be
@jsonSerializable
class Packaging {
String iri;
num weight;
Map<String, dynamic> _extraPropsMap = {};
bool _isPackaged;
@jsonProperty
void unmappedSet(String name, dynamic value) { // Deserialization
_extraPropsMap[name] = value;
if (name == 'packaging' && value is String) {
iri = value
} else {
_isPackaged = true;
// value should be as of type Map<String, dynamic>
iri = value['iri'];
}
}
@jsonProperty
Map<String, dynamic> unmappedGet() { // Serialization
if (_isPackaged == true) {
_extraPropsMap['packaging'] = ...
}
return _extraPropsMap;
}
}
from dart-json-mapper.
I ended up with the following solution :
@observable
@JsonProperty(converter: CustomDynamicConverter(), converterParams: {'type': Packaging})
Packaging packaging;
class CustomDynamicConverter extends BaseCustomConverter
implements ICustomConverter<dynamic> {
const CustomDynamicConverter() : super();
@override
dynamic fromJSON(dynamic jsonValue, [JsonProperty jsonProperty]) {
if (jsonValue is Iterable) {
return jsonValue;
}
final context = DeserializationContext(
DeserializationOptions(), getModelType(jsonProperty));
if (jsonValue is String) {
final model = getInstance(context);
model.iri = jsonValue;
return model;
}
if (jsonValue is Map<String, dynamic>) {
if (!jsonValue.containsKey('iri')) {
return jsonValue;
}
print(jsonValue);
print(getModelType(jsonProperty));
return JsonMapper().deserializeObject(jsonValue, context);
}
if (jsonValue is Store) {
return jsonValue;
}
}
@override
dynamic toJSON(dynamic object, [JsonProperty jsonProperty]) {
return object;
}
Type getModelType([JsonProperty jsonProperty]) {
return getConverterParameter('type', jsonProperty) as Type;
}
dynamic getInstance(DeserializationContext context) {
final instanceType = context.instanceType.toString();
final cm = JsonMapper().classes[instanceType];
if (cm == null) {
throw MissingAnnotationOnTypeError(context.instanceType);
}
final classInfo = ClassInfo(cm);
return context.options.template ??
(cm.isEnum
? null
: cm.newInstance(
classInfo
.getJsonConstructor(context.options.scheme)
.constructorName,
null,
null));
}
}
I think I should have done more to fill all the newInstance parameters, but I don't need it for now.
from dart-json-mapper.
Related Issues (20)
- ignoreNullMembers Annotation is ignored HOT 7
- Flutter Json Mapper (json_mapper) is failing to deserialize Enum HOT 1
- Cannot deserialize to a class with a constructor that takes an enum HOT 4
- Can't add sources to `build.yaml` using `flutter_translate_annotations` package HOT 7
- ignoreNullMembers seems to break the deserialization HOT 2
- Problem converting enum with following uppercase character HOT 9
- Adapter for https://pub.dev/packages/fast_immutable_collections
- `main.mapper.g.dart` is not generating all `@jsonSerializable` classes HOT 6
- `JsonMapper.copyWith` doesn't respect deep merge
- Parsing error when building for web HOT 9
- Improve class instance creation error handling HOT 4
- Problem converting enum with following uppercase character - second edition :) HOT 10
- Omit serializing optional fields HOT 14
- Issues with deserialising Color HOT 3
- Dart Json Mapper looks like don't generate valueDecorators when models in different package HOT 1
- Default discriminatorValue may not work. HOT 4
- Using with Retrofit HOT 2
- Serialize generic type. HOT 1
- @Json takes no effect even if put on top class & processAnnotatedMembersOnly in option will ignore all members when serialization HOT 1
- Empty Reflectable file - regarding HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from dart-json-mapper.