Jackson - Json string to Java List of class - java

I am trying to map a JSON string to a Java class using Jackson.
public class ChartData {
List<String> xAxis=new ArrayList<String>();
List<String> yAxis=new ArrayList<String>();
List<String> zAxis=new ArrayList<String>();
String type;
public ChartData() {
}
public ChartData(String type, List<String> yAxis, List<String> zAxis) {
this.type = type;
this.yAxis = yAxis;
this.zAxis = zAxis;
}
The code I tried :
List<ChartData> emp = new ArrayList<>();
String o2 ="[{\"type\": \"2\", \"yAxis\": [\"11\"], \"zAxis\": [\"8\"]}, {\"type\": \"3\",
\"yAxis\": [\"17\", \"13\", \"12\"], \"zAxis\": [\"14\", \"13\", \"12\"]}]";
ObjectMapper mapper = new ObjectMapper();
data= (List<ChartData>) mapper.readValue(o2, ChartData.class);
return data;
But, I am getting the following error:
Can not deserialize instance of com.ChartData out of START_ARRAY token
at [Source: [{"type": "2", "yAxis": ["11"], "zAxis": ["8"]}, {"type":
"3", "yAxis": ["17", "13", "12"], "zAxis": ["14", "13", "12"]}]; line:
1, column: 1]
Where is my mistake?

There is a specific way to deserialize into list in jackson:
List<ChartData> data = mapper.readValue(o2 , new TypeReference<List<ChartData>>(){});
In your code you have also type mismatch in the conversion. You are using mapper.readValue(o2, ChartData.class) but you are casting it to List<ChartData>.
To maintain the basic type conversion (without TypeReference) you can deserialize the json into array in the following way:
ChartData[] data = mapper.readValue(o2 , ChartData[].class);
and afterwards convert it to a list if you need to.

Related

Deserialize a JSON array into a Java object (Not a List nor a Collection) using Jackson

I was previously using Gson and decided to move to Jackson for practical reasons.
Previously, I had a JSON deserializer that was deserializing an array of json objects into a single java object.
The json structure of the field is :
{
id: number,
type: (0 | 1),
allow: number,
deny: number
}[]
And I need to deserialize this array into my own object: PermissionOverwrites.
Previously, I was using this code with Gson:
JsonArray array = json.getAsJsonArray();
Map<Permissionable, Permissions> map = new HashMap<>();
for (JsonElement element : array) {
JsonObject object = element.getAsJsonObject();
Permissionable p = switch (object.get("type").getAsInt()) {
case 0 -> new Permissionable.MockPermissionable(object.get("id").getAsLong());
case 1 -> new Permissionable.MockPermissionable(object.get("id").getAsLong());
default -> throw new JsonParseException("Unknown permissionable type");
};
Permissions perms = new Permissions(object.get("allow").getAsLong(), object.get("deny").getAsLong());
map.put(p, perms);
}
return new PermissionOverwrites(map);
But now, with Jackson, I've got a JsonParser and a DeserializationContext and I can't find anything in any of the two files to parse an ArrayNode. Do you know any way I can do this using Jackson.
Thank you in advance!
EDIT:
PermissionsOverwrites.java
#ToString
#EqualsAndHashCode
public class PermissionOverwrites {
private Map<Permissionable, Permissions> overwrites;
public PermissionOverwrites(Map<Permissionable, Permissions> overwrites) {
this.overwrites = overwrites;
}
public PermissionOverwrites() {
this.overwrites = new HashMap<>();
}
public Map<Permissionable, Permissions> getOverwrites() {
return Collections.unmodifiableMap(overwrites);
}
}
Example of the JSON object:
[
{
"id": "111111111111111111",
"type": "0",
"allow": "01010",
"deny": "10101"
}
],
This code uses Jackson to do the same as your code that uses Gson:
JsonNode array = mapper.readTree(json);
for (JsonNode element : array) {
Map<Permissionable, Permissions> map = new HashMap<>();
Permissionable p = switch (element.get("type").asInt()) {
case 0 -> new Permissionable.MockPermissionable(element.get("id").asLong());
case 1 -> new Permissionable.MockPermissionable(element.get("id").asLong());
default -> throw new JsonParseException("Unknown permissionable type", null);
};
Permissions perms = new Permissions(element.get("allow").asLong(), element.get("deny").asLong());
map.put(p, perms);
}
return new PermissionOverwrites(map);
Here's an article about how to work with Jackson JSON tree model .

How to convert an json response like that?

I have a json reponse like given below.Basically,I want to convert an object and use it.
[
{
"Id": 1290,
"N": "Türkiye",
"Fid": 196,
"EC": 10,
"CL": null,
"SID": 0
},
{
"Id": 1239,
"N": "Dünya",
"Fid": 152,
"EC": 63,
"CL": null,
"SID": 0
}
]
... Goes on
Here is what I have tried,I am using org.json library.
String jsonString = response.body().string(); // Getting json response and converting to string.
JSONObject jsonResponse = new JSONObject( jsonString ); // Not working
JSONArray jsonArray = new JSONArray( jsonString ); // Not working
JSONArray matches = new JSONArray( jsonString ).getJSONArray(0); // Not working
But I am gettin those errors
A JSONObject text must begin with '{' at 0 [character 1 line 1]
A JSONArray text must begin with '{' at 0 [character 1 line 1]
I have checked topics like Parse JSON Array without Key. But the json described not like mine.
Any idea what should ı do?
in Java you would first need to define a class which has all the attributes
public class MyClass {
private int Id;
private int N;
private int Fid;
private int EC;
private int CL;
private int Sid;
// getters, setters, no arg constructor
}
then you can use for example gson library to parse it like this:
MyClass[] myClassArray = gson.fromJson(jsonString , MyClass[].class)
I really recommend you to use the Gson library it's way better to perform data operations:
public class User {
int id;
String n;
int fid;
int ec;
String cl;
int sid;
public static User[] parse(String s){
return new GsonBuilder().create().fromJson(s, User[].class);
}
}
Have you looked into Google's Gson? It is really easy to use and you can both serialize and deserialize objects.
Here is an example:
public Company[] deserializeCompany() {
Gson gson = new Gson();
Company[] companies = gson.fromJson(companiesJSON, Company[].class);
return companies;
}
First you need to make a template class that has a member field for each key in the json. E.g. private String id for the 'Id' key in the json you provided. In my example it is the Company class.
Next you make a new Gson object using Gson gson = new Gson(); and use the .fromJson function supplying it both the Json array and the Object array type (which is of the form MyClass[].class).
First, your question is not to convert a JSON array without key. Second, there are many popular JSON libraries can achieve what you want such as org.json, Jackson, Gson and so on.
Here comes several examples:
With org.json, you can retrieve field values in a JSON array as follows:
JSONArray jsonResponse = new JSONArray(jsonStr);
System.out.println(jsonResponse.get(0).toString());
System.out.println("Id: " + jsonResponse.getJSONObject(0).get("Id"));
System.out.println("N : " + jsonResponse.getJSONObject(0).get("N"));
And the expected output should be:
{"Fid":196,"CL":null,"Id":1290,"N":"Türkiye","EC":10,"SID":0}
Id: 1290
N : Türkiye
With Jackson, you can retrieve field values in a JSON array as follows:
ObjectMapper objectMapper = new ObjectMapper();
List<Map<String, Object>> jsonResponse = objectMapper.readValue(jsonStr, new TypeReference<List<Map<String, Object>>>() {});
System.out.println(jsonResponse.toString());
System.out.println("Id: " + jsonResponse.get(0).get("Id"));
System.out.println("N : " + jsonResponse.get(0).get("N"));
And the expected output should be:
{Id=1290, N=Türkiye, Fid=196, EC=10, CL=null, SID=0}
Id: 1290
N : Türkiye
3. Furthermore, if you define a POJO as follows:
class MyObject {
private #JsonProperty("Id") int id;
private #JsonProperty("N") String n;
private #JsonProperty("Fid") int fid;
private #JsonProperty("EC") int ec;
private #JsonProperty("CL") int cl;
private #JsonProperty("SID") int sid;
//general getters, setters and toString
}
Then you can deserialize the JSON response to your POJO by:
ObjectMapper objectMapper = new ObjectMapper();
List<MyObject> jsonResponse = objectMapper.readValue(jsonStr, new TypeReference<List<MyObject>>() {});
System.out.println(jsonResponse.get(0).toString());
System.out.println("Id: " + jsonResponse.get(0).getId());
System.out.println("N : " + jsonResponse.get(0).getN());
And the expected output should be:
MyObject{id=1290, n='Türkiye', fid=196, ec=10, cl=0, sid=0}
Id: 1290
N : Türkiye

Java - How can i read json file and put values into array

I have this JSON file called city.list.json, containing objects like these:
{
"id": 707860,
"name": "Hurzuf",
"country": "UA",
"coord": {
"lon": 34.283333,
"lat": 44.549999
}}
How can I put name's value into array?
This is the code I've tried:
String name = null;
JSONArray jsonArr = new JSONArray("[JSON String]");
ArrayList<Data> dataList = new ArrayList<>();
for (int i = 0; i < jsonArr.length(); i++) {
JSONObject jsonObj = jsonArr.getJSONObject(i);
Data data = new Data();
data.name = jsonObj.getString("name");
dataList.add(data);
}
But it gives me errors on data saying "Constructor Data in class Data cannot applied to given types"
You can use GSON library to achieve this task:
String input = yourSampleJson;
Gson gson = new Gson();
Map<String,Object> inputPojo = new HashMap<>();
inputPojo = gson.fromJson(input, inputPojo.class); // This map now contains the representation of your JSON.
I generally prefer having a POJO class which represents your JSON structure something as :
Class DanielePojo {
Integer id;
String name;
String country;
Coord coord; // This is another class similar to this POJO which is represented as Object in your JSON
// Then your getters and setters
}
Then you can convert JSON into Pojo object directly without having a MAP as an intermediate object.
DanielePojo pojo = new GSON.fromJSON(input,DanielePojo.class);

gson de-serialising object array without identifier

Im getting an error trying to take a json array to a list of objects, the exception is as below.
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 170
here is the code i am trying to use
public static void main(String[] args) throws FileNotFoundException {
Gson gson = new Gson();
Test test = new Test();
JsonElement json = gson.fromJson(test.getFile("fieldTypes.json"), JsonElement.class);
String result = gson.toJson(json);
System.out.println(result);
Type listType = new TypeToken<ArrayList<JiraField>>(){}.getType();
JiraField[] jiraFields = gson.fromJson(result, listType);
for (JiraField jiraField : jiraFields) {
System.out.println(jiraField);
}
}
This is the file contents
[
{
"id": "issuetype",
"key": "issuetype",
"name": "Issue Type",
"custom": false,
"orderable": true,
"navigable": true,
"searchable": true,
"clauseNames": [
"issuetype",
"type"
],
"schema": {
"type": "issuetype",
"system": "issuetype"
}
},
{
"id": "timespent",
"key": "timespent",
"name": "Time Spent",
"custom": false,
"orderable": false,
"navigable": true,
"searchable": false,
"clauseNames": [
"timespent"
],
"schema": {
"type": "number",
"system": "timespent"
}
}
]
The file is being read from the resources folder but that is working fine and the sysout is correctly showing the json contents. i assume there is something im doing wrong ?
ok, so. turns out to be caused by un mapped fields, this is how i got it working
in the object you add the #Expose annotation for the fields you want
public class JiraField {
#Expose
private String id ;
#Expose private String key ;
#Expose private String name ;
#Expose private boolean custom ;
#Expose private boolean orderable ;
#Expose private boolean navigable ;
#Expose private String[] clauseNames ;
Then when you initialise gson, you do it like this
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
then it works :)
JiraFields{id='issuetype', key='issuetype', name='Issue Type', custom=false, orderable=true, navigable=true, clauseNames=[issuetype, type]}
JiraFields{id='timespent', key='timespent', name='Time Spent', custom=false, orderable=false, navigable=true, clauseNames=[timespent]}
Try this:
Type listType = new TypeToken<ArrayList<JiraField[]>>(){}.getType();
I think we need to specify the JiraField[] in-order to get Array.
I'm assuming you have a minified JSON according to the exception message ...at line 1 column 170.... It would be nice if you provide both exact your exact JSON document and your mapping as well, since the posted formatted JSON now has the layout destroyed. I'm also assuming your mapping is custom and basically something like:
final class JiraField {
#SerializedName("id")
final String id = null;
#SerializedName("key")
final String key = null;
#SerializedName("name")
final String name = null;
#SerializedName("custom")
final boolean isCustom = Boolean.valueOf(false);
#SerializedName("orderable")
final boolean isOrderable = Boolean.valueOf(false);
#SerializedName("navigable")
final boolean isNavigable = Boolean.valueOf(false);
#SerializedName("searchable")
final boolean isSearchable = Boolean.valueOf(false);
#SerializedName("clauseNames")
final List<String> clauseNames = null;
#SerializedName("schema")
final List<String> schema = null;
}
Note the JiraField.schema field type: it's a list. Trying to deserialize a list of JiraFields with the default Gson configuration would result into:
java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 170 path $[0].schema
The symptom and the column are exactly the same (however, again, I'm just assyming your JSON file is minified), but note the path $[0].schema you probably missed to post: it says that an array begin token [ is expected (since the field is a List<String>), but was an object begin token {. Changing the field type to a more appropriate arbitrary Map<String, String> or any other custom appropriate POJO would fix it. Partially.
#SerializedName("schema")
final Map<String, String> schema = null;
Why partially? Your type token is bound to an ArrayList, but you're casting the deserialization result to an array JiraField[], therefore you'd get something like this:
Exception in thread "main" java.lang.ClassCastException: java.util.ArrayList cannot be cast to [LJiraField;
To fix it, you have to declare your jiraFields variable matching the deserialized value type: it's an array list, but not an array -- these are not the same in Java.
List<JiraField> jiraFields = ...
Another note regarding deserialization is that you don't need an intermediate json object to deserialize from. test.getFile most likely returns a java.io.Reader, so you can pass it directly to deserialize. Summarizing all up, the following should work for you:
// Immutable and thread-safe, can be instantiated once and shared
private static final Gson gson = new Gson();
// Immutable and thread-safe value type, the same story, + List instead of ArrayList - interfaces are usually much better
private static final Type listType = new TypeToken<List<JiraField>>() {
}.getType();
public static void main(final String... args)
throws IOException {
try ( final Reader reader = test.getFile("fieldTypes.json") ) {
final List<JiraField> jiraFields = gson.fromJson(reader, listType);
for ( final JiraField jiraField : jiraFields ) {
System.out.println(jiraField.key + " => " + jiraField.name);
}
}
}
Output:
issuetype => Issue Type
timespent => Time Spent
Type listType = new TypeToken<ArrayList<JiraField>>(){}.getType();
ArrayList<JiraField> jiraFields = gson.fromJson(result, listType);
for (JiraField jiraField : jiraFields) {
System.out.println(jiraField);
}
Try This code
Comment this line
Type listType = new TypeToken<ArrayList<JiraField>>(){}.getType();
Try with this
JiraField[] jiraFields = gson.fromJson(result, JiraField[].class);

How to convert List to a JSON Object using GSON?

I have a List which I need to convert into JSON Object using GSON. My JSON Object has JSON Array in it.
public class DataResponse {
private List<ClientResponse> apps;
// getters and setters
public static class ClientResponse {
private double mean;
private double deviation;
private int code;
private String pack;
private int version;
// getters and setters
}
}
Below is my code in which I need to convert my List to JSON Object which has JSON Array in it -
public void marshal(Object response) {
List<DataResponse.ClientResponse> clientResponse = ((DataResponse) response).getClientResponse();
// now how do I convert clientResponse list to JSON Object which has JSON Array in it using GSON?
// String jsonObject = ??
}
As of now, I only have two items in List - So I need my JSON Object like this -
{
"apps":[
{
"mean":1.2,
"deviation":1.3
"code":100,
"pack":"hello",
"version":1
},
{
"mean":1.5,
"deviation":1.1
"code":200,
"pack":"world",
"version":2
}
]
}
What is the best way to do this?
There is a sample from google gson documentation on how to actually convert the list to json string:
Type listType = new TypeToken<List<String>>() {}.getType();
List<String> target = new LinkedList<String>();
target.add("blah");
Gson gson = new Gson();
String json = gson.toJson(target, listType);
List<String> target2 = gson.fromJson(json, listType);
You need to set the type of list in toJson method and pass the list object to convert it to json string or vice versa.
If response in your marshal method is a DataResponse, then that's what you should be serializing.
Gson gson = new Gson();
gson.toJson(response);
That will give you the JSON output you are looking for.
Assuming you also want to get json in format
{
"apps": [
{
"mean": 1.2,
"deviation": 1.3,
"code": 100,
"pack": "hello",
"version": 1
},
{
"mean": 1.5,
"deviation": 1.1,
"code": 200,
"pack": "world",
"version": 2
}
]
}
instead of
{"apps":[{"mean":1.2,"deviation":1.3,"code":100,"pack":"hello","version":1},{"mean":1.5,"deviation":1.1,"code":200,"pack":"world","version":2}]}
you can use pretty printing. To do so use
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(dataResponse);
Make sure to convert your collection to Array:
Gson().toJson(objectsList.toTypedArray(), Array<CustomObject>::class.java)
We can also use another workaround by first creating an array of myObject then convert them into list.
final Optional<List<MyObject>> sortInput = Optional.ofNullable(jsonArgument)
.map(jsonArgument -> GSON.toJson(jsonArgument, ArrayList.class))
.map(gson -> GSON.fromJson(gson, MyObject[].class))
.map(myObjectArray -> Arrays.asList(myObjectArray));
Benifits:
we are not using reflection here. :)

Categories

Resources