Parsing specific JSON with Gson - java

I'm currently trying to parse a JSON response with the following structure using Gson:
{
data {
"1": {
"name": "John Doe"
},
"2": {
"name": "John Doe"
},
...
}
My response class:
class Response {
Map<String, ModelObj> data;
}
and model class:
class ModelObj {
String name;
}
But what I can't figure out is how to simply map everything to a single List where the id is placed within the ModelObj without having them separate as key/value pairs in a Map. So ideally my response class would be:
class Response {
List<ModelObj> data;
}
and model class:
class ModelObj {
String id;
String name;
}
How would this be accomplished?

[
{
"id": 1,
"name": "John Doe"
},
{
"id": 2,
"name": "John Doe"
}
]
If your response is of above form then only you will get the list of model object and you will get Array of ModelObj
then use below code to convert to List
public <T> List<T> getObjectToList(String json, Class<T[]> ObjectArrayClass) {
return Arrays.asList(gson.fromJson(json, ObjectArrayClass));
}
List< ModelObj > arrayList = getObjectToList(jsonResponseString, ModelObj[].class);

Related

Mapping a List inside a List using SerializedName

I have an object class, called Device, inside that there is a List of objects, which also contains a List of objects.
Model looks like this:
public class Device {
#SerializedName("tests")
public List<Test> tests;
public static class Test {
#SerializedName("id")
public String id;
#SerializedName("testInfo")
private List<TestInfo> testInfo = new ArrayList<TestInfo>();
}
public static class TestInfo {
#SerializedName("id")
private String id;
}
}
Now when it is mapping the request, it maps the first List, meaning when printing the result I get this:
Test{id='123', testInfo = []}
Test{id='124', testInfo = []}
The testInfo is always an empty list, even though the data is there. I tried it with and without the new ArrayList. Is the problem here that SerializedName does not know how to map a list inside a list or am I doing somthing wrong?
EDIT
Data that is being mapped:
"tests": [
{
"id": "123",
"testInfo": [
{
"id": "321",
},
{
"id": "322",
}
]
},
{
"id": "124",
"testInfo": [
{
"id": "421",
},
{
"id": "422",
}
]
},
]

JSON parse error: Can not deserialize instance - Java

I'm creating a REST service that receives a JSON input like this:
[
{
"person": {
"name": "string",
"surname": "string",
"address": "string",
"age": "data",
"info": {
"number": "string"
}
}
},
{
"person": {
"name": "string",
"surname": "string",
"address": "string",
"age": "data",
"info": {
"number": "string"
}
}
}
]
My items are(
I omitted getters and setters):
public class Request {
private List<Person> person;
}
public class Person{
private String name;
private String surname;
private String address;
private XMLGregorianCalendar age;
private Info info;
}
public class Info {
private String number;
}
how come i get the following error?
{
"timestamp": 1611142052198,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.http.converter.HttpMessageNotReadableException",
"message": "JSON parse error: Can not deserialize instance of com.myproject.model.Request out of
START_ARRAY
}
i need the json structure to be exactly that.
You are trying to de-serialize your input array to a Request object, which is not a collection, and thus you get that error.
To solve it you should de-serialize your input array to a List<Person> object and then set that object to your Request object:
Request request = ... // get the request
List<Person> person = ... // deserialize the input array
request.setPerson(person);
If you are using Jackson, you can also define a constructor for your Request class which takes a List<Person> argument and then mark that constructor with the #JsonCreator annotation (see here for an example):
public class Request {
private List<Person> person;
#JsonCreator
public Request(#JsonProperty("person") List<Person> person) {
this.person = person;
}
}
And then you can create your Request object directly from your input array.
By using the #JsonCreator annotation you keep your Request class immutable, because you don't need to define a setPerson(List<Person>) method for it.

Custom Gson serializer with fields that are unknown at runtime

I'm attempting to do custom Gson serialization to create a Json object to send to a service except their are some fields that are not known at runtime.
The json I wish to create should look something like this:
{
"type": "configuration/entityTypes/HCP",
"attributes": {
"FirstName": [
{
"type": "configuration/entityTypes/HCP/attributes/FirstName",
"value": "Michael"
}
]
},
"crosswalks": [
{
"type": "configuration/sources/AMA",
"value": "10000012"
}
]
}
I am able to successfully create this json using Gson, but the issue is that I have thousands of fields that could be under the attributes object, in this example there is only the FirstName but if I was doing a create there would be as many attributes as that person, place or thing had associated with them.
Because currently I am able to create this using Gson by having 4 different classes:
Type
Attributes
FirstName
Crosswalks
But I want to be able to have FirstName, LastName, MiddleName, etc. all underneath the attributes object without creating an individual java class for all of them. The json would look like this in that case:
{
"type": "configuration/entityTypes/HCP",
"attributes": {
"FirstName": [
{
"type": "configuration/entityTypes/HCP/attributes/FirstName",
"value": "Doe"
}
],
"LastName": [
{
"type": "configuration/entityTypes/HCP/attributes/LastName",
"value": "John"
}
],
"MiddleName": [
{
"type": "configuration/entityTypes/HCP/attributes/MiddleName",
"value": "Michael"
}
]
},
"crosswalks": [
{
"type": "configuration/sources/AMA",
"value": "10000012"
}
]
}
Is there a way to use Gson to create the attributes object without creating java objects for all of the different attributes I have?
You can use Map<String, Object> where Object will be an one-element-array. See, for example, below model:
class Attributes {
private Map<String, Object> attributes;
// getters, setters
}
class Type {
private final String type;
private final String value;
public Type(String type, String value) {
this.type = type;
this.value = value;
}
// getters
}
Now, let's build attributes manually:
import com.google.gson.Gson;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class GsonApp {
public static void main(String[] args) {
Map<String, Object> map = new HashMap<>();
map.put("FirstName", Collections.singletonList(new Type("url/FirstName", "Rick")));
map.put("LastName", Collections.singletonList(new Type("url/LastName", "Pickle")));
Attributes attributes = new Attributes();
attributes.setAttributes(map);
String json = new Gson().newBuilder().setPrettyPrinting().create().toJson(attributes);
System.out.println(json);
}
}
Above code prints:
{
"attributes": {
"FirstName": [
{
"type": "url/FirstName",
"value": "Rick"
}
],
"LastName": [
{
"type": "url/LastName",
"value": "Pickle"
}
]
}
}

serialize json to pojo class

I have a JSON response coming as shown below. I am trying to make a POJO for this so that I can serialize this JSON into my POJO.
{
"holder": [
{
"ids": [
{
"data": "abcdef1234",
"time": 1452720139465,
"days": 16813
},
{
"data": "abcdef12345678",
"time": 1452720139465,
"days": 16813
},
{
"data": "abcdef12345678901234",
"time": 1452720139465,
"days": 16813
}
],
"type": "HELLO"
}
]
}
And this is my POJO I was able to come up with but it doesn't look right.
public class TestResponse {
private List<Ids> holder;
private String type;
// getters and setters
public static class Ids {
private String data;
private long time;
private long days;
// getters and setters
}
}
My json is not getting serialized to my above POJO
go to this link www.jsonschema2pojo.org and past yout json and extract jar files and import in your project and do some changes link this.
$class TestResponse {
to
class TestResponse implement serializable{

Gson deserialization with customer model

I have a json in a specific form that I have to deserialize.
In order to do that, I thought at my very best library Gson, but I'm facing a problem here because I have some key that are dynamic.
I think you will understand with a good exemple.
Here is the json :
{
"institution1": {
"_id": "51cc7bdc544ddb3f94000002",
"announce": { },
"city": "Melun",
"coordinates": [
2.65106,
48.528976
],
"country": "France",
"created_at": "2013-06-27T17:52:28Z",
"name": "italien",
"state": "Seine et Marne",
"street": "Avenue Albert Moreau",
"updated_at": "2013-06-27T17:52:28Z"
},
"institution2": {
"_id": "51d1dfa8544ddb9157000001",
"announce": {
"announce1": {
"_id": "51d1e036544ddb9157000002",
"created_at": "2013-07-01T20:02:35Z",
"description": "description formule 1",
"institution_id": "51d1dfa8544ddb9157000001",
"title": "formule dejeune",
"type": "restoration",
"updated_at": "2013-07-01T20:02:35Z"
},
"announce2": {
"_id": "51d1e074544ddb9157000003",
"created_at": "2013-07-01T20:03:08Z",
"description": "description formule soir",
"institution_id": "51d1dfa8544ddb9157000001",
"title": "formule soiree",
"type": "restoration",
"updated_at": "2013-07-01T20:03:08Z"
}
},
"city": "Melun",
"coordinates": [
2.65106,
48.528976
],
"country": "France",
"created_at": "2013-07-01T19:59:36Z",
"name": "restaurant francais chez pierre",
"state": "Seine et Marne",
"street": "Avenue Albert Moreau",
"updated_at": "2013-07-01T19:59:36Z"
}
}
You can go here for a better view.
So, I created a class to do that, JsonModel.java
public class JsonModel
{
public HashMap<String, Institution> entries;
public static class Institution
{
public String _id;
public HashMap<String, Announce> announce;
public String city;
public String country;
public List<Double> coordinates;
public String created_at;
public String name;
public String state;
public String street;
public String updated_at;
}
public static class Announce
{
public String _id;
public String created_at;
public String description;
public String institution_id;
public String title;
public String type;
public String updated_at;
}
}
And then, I asked Gson to deserialize that with the following code :
JsonModel data = new Gson().fromJson(json, JsonModel.class);
As data is null I presume that it is not working the way I expected...
And I thought about using HashMap because I don't know in advance the key like institution1, institution2, ...
What do you think ? Can I do that ?
And please don't tell me to use bracket, I just dream to have those !
Thank you in advance !
EDIT :
I was able to make this thing work by adding a root object
{
"root":{ ..the json.. }
}
AND changing
public HashMap<String, Institution> entries;
by
public HashMap<String, Institution> root;
So, the problem is gson need to recognise the first element but in fact I will not be able to modify the json, is there a way to get it done differently ?
The use of a Map is perfect, but you can't use your JsonModel class, because with that class you're assuming that in your JSON you have an object that contains a field called "entries" that in turn represents a map, like this:
{
"entries": { the map here... }
}
And you don't have that, but your JSON represents directly a map (not an object with a field called entries that represents a map!). Namely, you have only this:
{ the map here... }
So you need to parse it accordingly, removing the class JsonModel and using directly a Map to deserialize...
You need to use a TypeToken to get the type of your Map, like this:
Type mapType = new TypeToken<Map<String, Institution>>() {}.getType();
And then use the method .fromJson() with that type, like this:
Map<String, Institution> map = gson.fromJson(json, mapType);

Categories