How to works with two json formats with Jackson - java

I have class with field names:
private List<String> names;
Json that I'm getting looks like:
"names": [
{
"name": "a",
},
{
"name": "b",
},
{
"name": "c",
}
]
So I use custom serializing for transform this json to List:
#JsonProperty("names")
private void deserializeNames(List<Map<String, String>> json) {
names = json.stream().map(e -> e.get("name")).collect(Collectors.toList());
}
And this solution works, but when I will want to serialize objects of my class, new json will looks like:
"names": [
"a",
"b",
"c"
]
And my code for custom serializing won't work with it because it expects Map instead List
I tried to solve the problem using instanceof or deserialize list to map, but I think this is a wrong solution.
Is there any easy solutions for this problem?

You need not write custom Deserialiser for this,
You can define a class,
class Name {
#JsonProperty("name")
String name;
Name () {
}
}
You can use,
#JsonProperty("names")
private List<Name> names;
This will deserialise automatically. While serialising it will do the same.

Related

Java Rest Assured - how to sort JSON response

Java Rest Assured - how to sort JSON response
[
{
"name": "firstName",
"age": 22
},
{
"name": "AnotherName",
"age": 33
}
]
I have list of many objects - after deserlizlization to Java objects I want to SORT it based on age value - so the first shoulb be object with age 33.
First, create a POJO representing the deserialized object:
#Data
public class YourObject {
private String name;
private int age;
}
Then you can deserialize your JSON string to List<YourObject> by using Jackson's ObjectMapper
List<YourObject> list = new ObjectMapper().readValue(json, new TypeReference<List<YourObject>>(){});
Then use List.sort and Comparator to sort this list by descending order.
list.sort(Comparator.comparing(YourObject::getAge, Collections.reverseOrder()));

org.json.simple. get unique nested value

I have a json with complex nested. values. But there is one unique key value pair in the json.. without traversing , I need to retrieve the value .
for example:
name : "xyz". In the entire complex nested json , I need to return a json with all the values of name key.
I am currently using org.simple.json. but its very complex as I have to traverse through the entire nested json and build JSONArray etc.
maybe you can use java8 stream,the way is very easy to solve your problem.
example:
[
{
"name":"xyz",
"value":"1"
},
{
"name":"xyz",
"value":"2"
},
{
"name":"xyz",
"value":"3"
}
]
and then,you can create a class:
import lombok.Data;
#Data
public class JsonTest {
private String name;
private String value;
}
finally, like this. btw, I am currently using other json package.
List<JsonTest> jsonArray = JSON.parseArray(json, JsonTest.class);
List<String> valueList = jsonArray.stream()
.filter(e -> "xyz".equals(e.getName()))
.map(JsonTest::getValue)
.collect(Collectors.toList());

How can I map in JAVA with JACKSON an array from a JSON which can contain differently typed objects as items?

As you can see in the example below, the first item in the attributes array is an object consisting of two string properties. The second object consists of a string and array property. I would like to decode both of these types of JSON objects into a collection of Java objects.
How I can express this in a POJO java class to handle decoding JSON like this?
attributes:[
{
"attribute_code": "has_options",
"value": "0"
},
{
"attribute_code": "ewc_top_quick",
"value": [
{
"label": "Display",
"value": "12.5",
"suffix": "''"
},
{
"label": "Grafica Integrata",
"value": "1",
"suffix": ""
}
]
}
]
So, you can use Map<String, Object> fro this field.
class Attr {
private String attribute_code;
private Map<String, Object> value;
}
After this, you can work with this object.
Also, you can use #JsonAnySetter. It's something similar to the previous option.
And the best way to resolve your situation it's custom deserializer. I strongly recommended this option.

How to deserialize this dynamic valued JSON?

I want to deserialize the following JSON (in the original there are about 100 Exchanges with dynamic values):
{
"Exchange1": {
"EUR": [
"CNY",
"USD"
],
"INR": [
"USD",
"CNY"
]
},
"Exchange2": {
"BRL": [
"EUR",
"USD",
"INR"
],
"JPY": [
"USD",
"EUR",
"CNY"
]
},
....
}
I am using http://www.jsonschema2pojo.org/ but it is generating a Java class taking literal values ("Exchange1", "EUR", etc) while I need to iterate this no matter what is the dynamic String value:
How can I describe this JSON with Java?
You cannot have POJOs here (in sane sense), but people tend to use POJO-generators that do not do ahead analysis even for dynamic objects.
"Dynamic" objects should be typically mapped using java.util.Map (ordered implementation) + unique values can be mapped using java.util.Set (ordered implementation).
Thus, if you have a custom enumeration for the currencies, say something like
enum Currency {
BRL,
CNY,
EUR,
INR,
JPY,
USD,
}
then you can easily define the mapping without any POJOs that do not look applicable here at all:
private static final Type exchangesType = new TypeToken<Map<String, Map<Currency, Set<Currency>>>>() {
}.getType();
final Map<String, Map<Currency, Set<Currency>>> exchanges = gson.fromJson(jsonReader, exchangesType);
System.out.println(exchanges);
So the trivial toString() output will be as follows:
{Exchange1={EUR=[CNY, USD], INR=[USD, CNY]}, Exchange2={BRL=[EUR, USD, INR], JPY=[USD, EUR, CNY]}}
If you don't like the idea of having the Currency enumeration (you must always keep it up to date with recompilation, etc), then you can simply declare the currency markers as java.lang.String and get the same result:
private static final Type exchangesType = new TypeToken<Map<String, Map<String, Set<String>>>>() {
}.getType();
final Map<String, Map<String, Set<String>>> exchanges = gson.fromJson(jsonReader, exchangesType);
System.out.println(exchanges);

Jackson - Processing JSON with multiple types

Say I have a JSON file that looks like this:
{
"response" : [
{
"id" : "10",
"period" : "month",
"values" : [
{
"value" : 100,
"date" : "2013-05-10"
}
],
"parent" : "1"
},
{
"id" : "10",
"period" : "day",
"values" : [
{
"value" : {
"foo" : 10,
"bar" : 11,
"etc" : 4
},
"date" : "2013-05-10"
}
],
"parent" : "1"
},{
"id" : "13",
"period" : "year",
"values" : [
{
"value" : {
"info" : 1,
"pages" : 10,
"etc" : 4
},
"date" : "2013-05-10"
}
],
"parent" : "1"
}
]
}
Notice the 'values' part can either be a single value, or an object (which is unique).
I want to use the Jackson ObjectMapper to easily map this to a POJO.
What I have so far:
public class Response
{
List<ResponseEntry> response;
/*getters + setters */
public static class ResponseEntry
{
private String id;
private String period;
private String parent;
private List<Value> values;
/*setters + getters*/
public static class Value
{
private Object value;
private String date;
/*setters+getters*/
}
}
}
To map the response, I just specify the file I want and tell ObjectMapper to map to the 'Response' class
ObjectMapper mapper = new ObjectMapper();
Response r = mapper.readValues(json, Response.class);
This works, but is there a better way than just using 'Object' to hold 'value'? Since 'value' can be either a single value or an object, I'm having a bit of difficult figuring out what it should be. I'm certain there is a polymorphic way of handling this, but I've looked and couldn't find anything that worked. I'm pretty stuck and I would appreciate any help.
Unfortunately, with the structure of the JSON you are handling, the only way to deserialize it is to have the value attribute be type Object. However, once the JSON is deserialized, you can easily figure out whether value is an object or a single value.
Notice that JSON only supports five data types: objects (Map in java), arrays, strings, numeric and boolean. It looks like in your case, value would most likely be either a number or a map of numbers; then you have two possibilities to check for. Using a quick instanceof comparison, you should be able to figure out what type of value it is.
ObjectMapper mapper = new ObjectMapper();
Response r = mapper.readValues(json, Response.class);
Value val = r.response.get(0).values.get(0);
if (val.value instanceof Map)
; // multiple
else
; // single

Categories

Resources