Parse JSON object as Interface in Dart - json

I have an interface Employee and Department. I'm loading JSON from server that I need to "parse" to object that implements those interfaces. Is there a way how to achieve this automatically since all types in interface and JSON object are base types (String, number, list, map)?
// Abstract classes represents interfaces
abstract class Employee {
String firstName;
String lastName;
}
abstract class Department {
String name;
List<Employee> employees;
}
// JSON
{
"name": "Development",
"employees":
[
{"firstName":"John", "lastName":"Doe"},
{"firstName":"Anna", "lastName":"Smith"},
{"firstName":"Peter", "lastName":"Jones"}
]
}
I want to parse it like this
main() {
...
Department department = someMethodToParse(jsonFromServer);
...
}

There are a few packages that deal with JSON de/serialization
http://www.dartdocs.org/documentation/serialization/0.9.1+1/index.html#serialization/serialization (serialization package)
Can I automatically serialize a Dart object to send over a Web Socket? (package exportable)
Convert JS object into Dart classes (manual)
How to convert an object containing DateTime fields to JSON in Dart? (handling DateDime)
Add JSON serializer to every model class?

Related

Convert JSON properties with under_score to DTO with lowerCamel properties using Gson

I'm facing some difficulties while trying to convert JSON response which contains properties with under_score, to DTO with lowerCamelCase properties.
JSON for example:
{
"promoted_by": "",
"parent": "",
"caused_by": "jenkins",
"watch_list": "prod",
"u_automation": "deep",
"upon_reject": "cancel"
}
DTO for example:
#Data
public class TicketDTO {
private String promotedBy;
private String parent;
private String causedBy;
private String watchList;
private String uAutomation;
private String uponReject;
}
Mapper:
#Mapper(componentModel = "spring")
public interface ITicketMapper {
default TicketDTO toDTO(JsonObject ticket) {
Gson gson = new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
.create();
return gson.fromJson(incident, TicketDTO.class);
}
}
This example is not working of course, I would like to know if it's possible to do this conversion with Gson.
Appriciate your help.
You should use LOWER_CASE_WITH_UNDERSCORES
Using this naming policy with Gson will modify the Java Field name from its camel cased form to a lower case field name where each word is separated by an underscore (_).
Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":
someFieldName ---> some_field_name
someFieldName ---> _some_field_name
aStringField ---> a_string_field
aURL ---> a_u_r_l
setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
The UPPER_CAMEL_CASE is used for different purpose
Using this naming policy with Gson will ensure that the first "letter" of the Java field name is capitalized when serialized to its JSON form.

How to parse json arrary?

I have come across a problem of parsing json data . I am building project using spring boot based on REST api . When i have to parse data corresponding to domain then it is very easy , i use RequestBody in controller method with domain name but in current scenerio i have a list of domain in json form :
{
"data":[
{
"type":"abc",
"subtypes":[
{
"leftValue":"BEACH",
"rightValue":"MOUNTAIN",
"preferencePoint":60
},
{
"leftValue":"ADVENTURE",
"rightValue":"LEISURE",
"preferencePoint":60
}
]
},
{
"type":"mno",
"subtypes":[
{
"leftValue":"LUXURY",
"rightValue":"FUNCTIONAL",
"preferencePoint":60
},
{
"leftValue":"SENSIBLE",
"rightValue":"AGGRESIVE",
"preferencePoint":0
}
]
}
]
}
I am sending data in list where type is the property of class Type
and class Type has list of Subtypes class and subtype class contains leftValue and rightValue as enums
I am using spring boot which uses jackson liberary by default and i want to parse this data into corresponding Type class using Jackson. Can any one provide me solution.
It wasn't clear to me if you have static or dynamic payload.
Static payload
For static one, I would personally try to simplify your payload structure. But your structure would look like this. (I skipped getters and setters. You can generate them via Lombok library).
public class Subtype{
private String leftValue;
private String rightValue;
private int preferencePoint;
}
public class Type{
private String type;
private List<Subtype> subtypes;
}
public class Data{
private List<Type> data;
}
Then in your controller you inject Data type as #RequestBody.
Dynamic payload
For dynamic payload, there is option to inject LinkedHashMap<String, Object> as #RequestBody. Where value in that map is of type Object, which can be casted into another LinkedHashMap<String, Object> and therefore this approach support also nested objects. This can support infinite nesting this way. The only downside is that you need to cast Objects into correct types based on key from the map.
BTW, with pure Spring or Spring Boot I was always able to avoid explicit call against Jackson API, therefore I don't recommend to go down that path.

Jackson Polymorphism Deserialize empty JSON object

I have a Jackson polymorphic question.
I want to deserialize JSON data into polymorphic types. Reading Jackson documentation, I can deserialize JSON data to polymorphic types. However, I have a special case. I have a class structure as follows:
class Supreme {
private String type;
}
class Foo extends Supreme {
public String label;
}
class Bar extends Supreme {
}
Note: Class Bar does not have any other member variable other than the inherited "type" field.
I have transformed that structure to:
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME,include = JsonTypeInfo.As.PROPERTY,property ="type")
#JsonSubTypes({#Type(value = Foo.class, name = "Foo"),#Type(value = Bar.class, name = "Bar") })
class Supreme {
}
class Foo extends Supreme {
public String label;
}
class Bar extends Supreme {
}
String data=
"[{
"type": "Foo",
"label": "abc"
},
{
"type": "Bar"
}]"
If I pass in the above json data like:
new ObjectMapper().readValue(data, new TypeReference<List<Supreme>>());
I get something like "Unable to deserialize class Bar out of the END_TOKEN". And I believe that is because the JsonTypeInfo and JsonSubTypes annotations have parsed "type" property and figured out that the 2nd entity in the array should be mapped to Bar class; however it tries to find "something" after the type property in that 2 entity. In other words, Jackson thinks it is an empty JSON object.
(Note: the above data without the 2nd entry in the array works fine. In other words, we can deserialize to a list containing Foo object since it at least has a property other than "type")
Any idea how to get around this?
By mistake, I was using Jackson 1.5
I bumped to Jackson 1.9 and the exception went away. So there was a bug in Jackson 1.5

Binding Raw JSON With The Fields Of Different Classes

I am getting following JSON string through http webservice:
Raw JSON String:
[
{
field1OfClass1:"someValue",
field2OfClass1:"someValue",
field1OfClass2:"someValue",
field2OfClass3:"someValue"
}
]
Classes:
class Class1
{
String field1;
String field2;
}
class Class2
{
String field1;
}
class Class3
{
String field2;
}
In GSON is there any way to parse above said JSON string with the fields of depicted classes?
Thanks
As best I know, there is no built-in feature of Gson to automagically map the example JSON structure to the example Java data structure in the original question. Custom deserialization processing is necessary.

Jackson JSON to Java mapping for same attrubute with different data type

I have a JSON object which I don't have control of and want to map it to a Java object which is pre-created.
There is one attribute in the JSON object which can be a URL or it could be a JSONArray.
Class SomeClass {
private URL items;
public URL getURL() {
return items;
}
public void setURL(URL url) {
this.items = url;
}
}
Below is the JSON:
Case A:
{
...
items: http://someurl.abc.com/linktoitems,
...
}
OR
Case B
{
...
items: [
{ "id": id1, "name": name1 },
{ "id": id2, "name": name2 }
]
...
}
If i create the POJO to map for Case A, Case B fails and vice versa. In short, is there a way to map the JSON attribute to the POJO field with different data types? In that case I will create two separate fields in the POJO named,
private URL itemLink;
private Item[] itemList;
It depends on exact details, but if what you are asking is if it is possible to map either JSON String or JSON array into a Java property, yes this can be done.
Obvious way would be to define a custom deserializer which handles both kinds of JSON input.
But it is also possible to define Java type in such a way that it can be constructed both by setting properties (which works from JSON Object) and have a single-String-arg constructor or static single-String-arg factory method marked with #JsonCreator.
Yet another possibility is to use an intermediate type that can deserialized from any JSON: both java.lang.Object and JsonNode ("JSON tree") instances can be created from any JSON. From this value you would need to do manual conversion; most likely in setter, like so:
public void setItems(JsonNode treeRoot) { .... }
What will not work, however, is defining two properties with the same name.
One thing I don't quite follow is how you would convert from List to URL though. So maybe you actually do need two separate internal fields; and setter would just assign to one of those (and getter would return value of just one).