I've looked all over and found some good answers to my question but i can't get it to work. I found this thread (Parsing single json entry to multiple objects with Gson) but i don't understand where my problem is.
I want to read the file into new Objects (if it's possible with just one then even better but i couldn't find out how).
First the int threads and then the array of tools(where each tool is an Object)
This is my TXT file :
{
"threads": 4,
"tools": [
{
"tool": "gs-driver",
"qty": 35
},
{
"tool": "np-hammer",
"qty": 17
},
{
"tool": "rs-pliers",
"qty": 23
}
]
}
this is my deseralization class, and two of my object classes
import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.List;
public class Deserializer implements JsonDeserializer<ParseJson> {
public ParseJson deserialize(JsonElement json, Type type,
JsonDeserializationContext context) throws JsonParseException {
JsonObject obj = json.getAsJsonObject();
ParseJson test = new ParseJson();
test.setThreads(obj.get("threads").getAsInt());
Gson toolsGson = new Gson();
Type toolsType = new TypeToken<List<ParseTool>>(){}.getType();
List<ParseTool> toolsList = toolsGson.fromJson(obj.get("tools"), toolsType);
test.setTools(toolsList);
return test;
}
}
import java.util.List;
public class ParseJson {
private int threads;
private List<ParseTool> tools;
public void setThreads(int _threads) {
this.threads = _threads;
}
public int getThreads() {
return threads;
}
public void setTools(List<ParseTool> tools) {
this.tools = tools;
}
public List<ParseTool> getTools() {
return tools;
}
}
public class ParseTool {
private int qty;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getQty() {
return qty;
}
public void setQty(int qty) {
this.qty = qty;
}
}
I can get the "threads" but it doesn't parse the array for some reason.
Thanks,
ParseTool contains a propery named name, but the JSON indicates that it's named tool.
You should therefore rename the property name to tool:
public class ParseTool {
private int qty;
private String tool;
public String getTool() {
return tool;
}
public void setTool(String tool) {
this.tool = tool;
}
public int getQty() {
return qty;
}
public void setQty(int qty) {
this.qty = qty;
}
}
Related
I have a restApi which its response can be something like this (if there is only one object to return):
{
"keys":
{
"id":0,
"name":"john",
"pItems":12
}
}
or like this if there is more:
{
"keys":
[
{
"id":0,
"name":"john",
"pItems":12
},
{
"id":0,
"name":"john",
"pItems":12
}
]
}
When I use a list for Model object, the first case doesn't work.
How can I deserialize it using Gson and Retrofit2?
Ok you cannot change the design of the response, but are you sure you only can receive those responses? if is like this maybe you can create something like this:
class Response{
public Object keys
}
class UserResponse{
public int id;
public String name;
public int pItems;
}
So you going to have two cases:
you can receive an UserResponse object
you can receive a List of UserResponse object
Then to validate if is a List of UserResponse, can be something like this:
if (keys instanceof List<?>){
// then keys is a list
}else{
// then keys is a single object UserResponse
}
You can check if keys element is array or not and then deserialize accordingly.
Assuming, your Model class is UserWrapper.java
import java.util.List;
public class UserWrapper {
private List<User> keys;
public List<User> getKeys() {
return keys;
}
public void setKeys(List<User> keys) {
this.keys = keys;
}
}
User.java is class corresponding to each element of keys attribute.
public class User {
private int id;
private String name;
private int pitems;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPitems() {
return pitems;
}
public void setPitems(int pitems) {
this.pitems = pitems;
}
}
Code to deserialize based on type of keys
import java.util.ArrayList;
import java.util.List;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
public class GsonMain{
private static String json = "YOUR JSON";
public static void main(String[] args) {
Gson gson = new GsonBuilder().create();
JsonElement jsonElement = gson.fromJson(json, JsonElement.class);
JsonElement keyselement = jsonElement.getAsJsonObject().get("keys");
UserWrapper userWrapper = new UserWrapper();
if (keyselement.isJsonObject()) {
userWrapper.setKeys(new ArrayList<User>());
User user = gson.fromJson(keyselement, User.class);
userWrapper.getKeys().add(user);
} else if (keyselement.isJsonArray()) {
List<User> users = gson.fromJson(keyselement, new TypeToken<List<User>>() {
}.getType());
userWrapper.setKeys(users);
}
userWrapper.getKeys().forEach(user -> System.out.println(user.getName()));
}
}
I have some problem where I am getting my data from my API call when I print in the console. I am getting {id: 0000, label: TEST} as my results. What I need to do is populate the label to show in my dropdown as a value where the user can select from. Is there a way with my code below? thanks for the help.
Here is my code:
Using Jersey Library:
public List<JobSearchItem> getjobSearchList() {
Client restClient = ClientBuilder.newClient();
Response response = restClient.target("https://api.myjson.com/bins/7xq2x").request(MediaType.APPLICATION_JSON).get();
return response.readEntity(new GenericType<List<JobSearchItem>>() {});
}
#Override
public String toString() {
return new StringBuilder().append("[value=").append(value).append(", label=").append(label).append("]")
.toString();
}
As I mentioned in the comment, it is very easy if you use a library or framework that does the heavy lifting for you. Here's a very simple example of retrieving the list using Jersey.
import java.util.List;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
public class ListExtractor {
public static void main(String[] args) {
Client restClient = ClientBuilder.newClient();
Response response = restClient.target("https://api.myjson.com/bins/7xq2x").request(MediaType.APPLICATION_JSON).get();
List<Item> items = response.readEntity(new GenericType<List<Item>>() {});
items.forEach(System.out::println);
}
static class Item {
private String name;
private String abbreviation;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAbbreviation() {
return abbreviation;
}
public void setAbbreviation(String abbreviation) {
this.abbreviation = abbreviation;
}
#Override
public String toString() {
return new StringBuilder().append("[name=").append(name).append(", abbreviation=").append(abbreviation).append("]")
.toString();
}
}
}
UPDATE
I just modified the code a bit, so that it returns a list of items.
Warning: this is not production ready code. I haven't added any exception handling or logging, so that it remains short and conveys its purpose in a clear way.
You need to familiarise yourself with JSON serialisers/deserialisers, in order to understand what's going in the above example.
Explanation
If you look at the response from the link (https://api.myjson.com/bins/7xq2x), you see that it returns a JSON array, where each element of the array is:
{"name":"Alberta","abbreviation":"AB"}. The JSON deserialiser provided by Jersey can convert (deserialise) this JSON object into a Java object if you have a class that has two fields named name and abbreviation (and their corresponding getters and setters).
This line of code
response.readEntity(new GenericType<List<Item>>() {});
will work out of the box because we have provided the Item class with fields named just like the keys in the JSON object above:
class Item {
private String name;
private String abbreviation;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAbbreviation() {
return abbreviation;
}
public void setAbbreviation(String abbreviation) {
this.abbreviation = abbreviation;
}
#Override
public String toString() {
return new StringBuilder().append("[name=").append(name).append(", abbreviation=").append(abbreviation).append("]")
.toString();
}
}
Here's the modified example:
import java.util.List;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
public class ListExtractor {
public static void main(String[] args) {
List<Item> items = getItems();
items.forEach(System.out::println);
}
static List<Item> getItems() {
Client restClient = ClientBuilder.newClient();
Response response = restClient.target("https://api.myjson.com/bins/7xq2x").request(MediaType.APPLICATION_JSON).get();
return response.readEntity(new GenericType<List<Item>>() {});
}
static class Item {
private String name;
private String abbreviation;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAbbreviation() {
return abbreviation;
}
public void setAbbreviation(String abbreviation) {
this.abbreviation = abbreviation;
}
#Override
public String toString() {
return new StringBuilder().append("[name=").append(name).append(", abbreviation=").append(abbreviation).append("]")
.toString();
}
}
}
Jersey dependencies (Gradle):
implementation 'org.glassfish.jersey.core:jersey-client:2.25.1'
implementation 'org.glassfish.jersey.media:jersey-media-json-jackson:2.25.1'
implementation 'org.glassfish.jersey.media:jersey-media-jaxb:2.25.1'
I'm trying to read the values from a JSON URL, however I don't know how I can proceed with reading the values from a List inside of an Array? Below you will find my POJO, Main, and JSON code. Thank you so much for your help
POJO:
package org.jcexchange.FBApp;
import java.util.List;
import org.jcexchange.FBApp.Details;
public class Users {
private List<Details> Values;
public List<Details> getValues() {
return this.Values;
}
public void setValues(List<Details> Values) {
this.Values = Values;
}
}
public class Details {
private String user_name;
private String user_password;
private int age;
private String user_email;
public String getUserName() {
return this.user_name;
}
public void setUserName(String user_name) {
this.user_name = user_name;
}
public String getUserPassword() {
return this.user_password;
}
public void setUserPassword(String user_password) {
this.user_password = user_password;
}
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
public String getUserEmail() {
return this.user_email;
}
public void setUserEmail(String user_email) {
this.user_email = user_email;
}
}
Main:
public class Main {
public static void main(String[] args) {
try {
URL jsonURL = new URL("https://jchtest.herokuapp.com/index.php?
PW=2");
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
false);
Users[] a1 = mapper.readValue(jsonURL, Users[].class);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
}
I'm able to pull the JSON from a webservice, however I'm stuck trying to figure out how I could retrieve for instance the user_name from the first "Values" index of the JSON array
JSON:
[
{
"Values": {
"user_name": "jhart",
"user_password": "gooddeval1",
"age": 28,
"user_email": "heheh"
}
},
{
"Values": {
"user_name": "bdole",
"user_password": "Passwordd",
"age": 82,
"user_email": "hahah"
}
}
]
Well , it is a little confusing here may be because i dont have the full context. From the de-serializer you are telling me that i expect an Array of Users and then within each User i have a List of "Values" , but the JSON tells me that Values is a singular property for Users. Anyways , here is a sample that works on the assumption i have made. This can be fiddled around to change the collection and singular properties
import org.codehaus.jackson.annotate.JsonProperty;
public class Users {
#JsonProperty("Values")
private Details Values;
public Details getValues() {
return this.Values;
}
public void setValues(Details Values) {
this.Values = Values;
}
}
import org.codehaus.jackson.annotate.JsonProperty;
public class Details {
#JsonProperty("user_name")
private String user_name;
#JsonProperty("user_password")
private String user_password;
#JsonProperty("age")
private int age;
#JsonProperty("user_email")
private String user_email;
public String getUserName() {
return this.user_name;
}
public void setUserName(String user_name) {
this.user_name = user_name;
}
public String getUserPassword() {
return this.user_password;
}
public void setUserPassword(String user_password) {
this.user_password = user_password;
}
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
public String getUserEmail() {
return this.user_email;
}
public void setUserEmail(String user_email) {
this.user_email = user_email;
}
}
import java.net.URL;
import org.codehaus.jackson.map.ObjectMapper;
public class Main {
public static void main(String[] args) {
try {
URL jsonURL = new URL("https://jchtest.herokuapp.com/index.php?PW=2");
ObjectMapper mapper = new ObjectMapper();
Users[] a1 = mapper.readValue(jsonURL, Users[].class);
System.out.println(a1[0].getValues().getUserName());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
This prints "jhart" for me.
Please note : One thing you can try is based on the array/singular property you can populate the Object and write it as JSON. That way you can find what is different in what Jackson Deserializer expects vs What we are actually supplying.
I have the following JSON object and I want to deserialize it using Google's GSON library. Unfortunately I am unable to get the list correctly. GSON finds the first list entry but not the second.
This is the code I use for invoking GSON:
Mentions result = gson.fromJson(response, Mentions.class);
Here is my JSON File:
{
"mentions": [
{
"allEntities": [
{
"kbIdentifier": "YAGO:Bob_Dylan",
"disambiguationScore": "0.63692"
}
],
"name": "Dylan",
"bestEntity": {
"kbIdentifier": "YAGO:Bob_Dylan",
"disambiguationScore": "0.63692"
}
},
{
"name": "Duluth",
"bestEntity": {
"kbIdentifier": "YAGO:Duluth\\u002c_Minnesota",
"disambiguationScore": "0.63149"
}
}
]
}
And these are the plain old java objects I have created:
public class Mentions {
public List<Mention> mentions = new ArrayList<>();
}
public class Mention {
#SerializedName("bestEntity")
public BestEntity entity;
#SerializedName("name")
public String name;
}
public class BestEntity {
#SerializedName("kbIdentifier")
public String kbIdentifier;
#SerializedName("disambiguationScore")
public Double disambiguationScore;
}
I also tried directly deserializing the list, but it just gives me an error, saying that GSON expects the list to start at the beginning of the input.
Type datasetListType = new TypeToken<Collection<Mention>>() {
}.getType();
List<Mention> mentions = gson.fromJson(response, datasetListType);
Try this -
AllEntity.java
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class AllEntity {
#SerializedName("kbIdentifier")
#Expose
private String kbIdentifier;
#SerializedName("disambiguationScore")
#Expose
private String disambiguationScore;
public String getKbIdentifier() {
return kbIdentifier;
}
public void setKbIdentifier(String kbIdentifier) {
this.kbIdentifier = kbIdentifier;
}
public String getDisambiguationScore() {
return disambiguationScore;
}
public void setDisambiguationScore(String disambiguationScore) {
this.disambiguationScore = disambiguationScore;
}
#Override
public String toString() {
return "AllEntity [kbIdentifier=" + kbIdentifier
+ ", disambiguationScore=" + disambiguationScore + "]";
}
}
BestEntity.java
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class BestEntity {
#SerializedName("kbIdentifier")
#Expose
private String kbIdentifier;
#SerializedName("disambiguationScore")
#Expose
private String disambiguationScore;
public String getKbIdentifier() {
return kbIdentifier;
}
public void setKbIdentifier(String kbIdentifier) {
this.kbIdentifier = kbIdentifier;
}
public String getDisambiguationScore() {
return disambiguationScore;
}
public void setDisambiguationScore(String disambiguationScore) {
this.disambiguationScore = disambiguationScore;
}
#Override
public String toString() {
return "BestEntity [kbIdentifier=" + kbIdentifier
+ ", disambiguationScore=" + disambiguationScore + "]";
}
}
Mention.java
import java.util.ArrayList;
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Mention {
#SerializedName("allEntities")
#Expose
private List<AllEntity> allEntities = new ArrayList<AllEntity>();
#SerializedName("name")
#Expose
private String name;
#SerializedName("bestEntity")
#Expose
private BestEntity bestEntity;
public List<AllEntity> getAllEntities() {
return allEntities;
}
public void setAllEntities(List<AllEntity> allEntities) {
this.allEntities = allEntities;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public BestEntity getBestEntity() {
return bestEntity;
}
public void setBestEntity(BestEntity bestEntity) {
this.bestEntity = bestEntity;
}
#Override
public String toString() {
return "Mention [allEntities=" + allEntities + ", name=" + name
+ ", bestEntity=" + bestEntity + "]";
}
}
Main.java
import com.example.ElemntList;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class Main {
private static Gson gson;
static {
gson = new GsonBuilder().create();
}
/**
* #param args
*/
public static void main(String[] args) {
String s = "{\"mentions\":[{\"allEntities\":[{\"kbIdentifier\":\"YAGO:Bob_Dylan\",\"disambiguationScore\":\"0.63692\"}],\"name\":\"Dylan\",\"bestEntity\":{\"kbIdentifier\":\"YAGO:Bob_Dylan\",\"disambiguationScore\":\"0.63692\"}},{\"name\":\"Duluth\",\"bestEntity\":{\"kbIdentifier\":\"YAGO:Duluth\\u002c_Minnesota\",\"disambiguationScore\":\"0.63149\"}}]}";
ElemntList info = gson.fromJson(s, ElemntList.class);
System.out.println(info);
}
}
Result is -
ElemntList [mentions=[Mention [allEntities=[AllEntity [kbIdentifier=YAGO:Bob_Dylan, disambiguationScore=0.63692]], name=Dylan, bestEntity=BestEntity [kbIdentifier=YAGO:Bob_Dylan, disambiguationScore=0.63692]], Mention [allEntities=[], name=Duluth, bestEntity=BestEntity [kbIdentifier=YAGO:Duluth,_Minnesota, disambiguationScore=0.63149]]]]
Shouldn't you use the class you've created ? I.E Mentions
gson.fromJson(response, Mentions.class);
And if I were you, I would map all fields just in case you may need it, you're missing allEntities.
I'm being given a Json file with the form:
{
"descriptions": {
"desc1": "someString",
"desc2": {"name":"someName", "val": 7.0}
}
}
I have the POJO:
public class CustomClass {
Map<String, Object> descriptions;
public static class NameVal{
String name;
double val;
public NameVal(String name, double val){...}
}
}
I can recreate the json file with the code:
CustomClass a = new CustomClass();
a.descriptions = new HashMap<String, Object>();
a.descriptions.put("desc1", "someString");
a.descriptions.put("desc2", new CustomClass.NameVal("someName", 7.0));
new ObjectMapper().writeValue(new File("testfile"), a);
But, when I read the object back in using:
CustomClass fromFile = new ObjectMapper().readValue(new File("testfile"), CustomClass.class);
then fromFile.descriptions.get("desc2") is of type LinkedHashMap instead of type CustomClass.NameVal.
How can I get Jackson to properly parse the type of the CustomClass.NameVal descriptors (other than making some class that wraps the parsing and explicitly converts the LinkedHashMap after Jackson reads the file)?
Try this. Create a class Description with name and value attributes:
public class Description {
private String name;
private double val;
}
Now in your CustomClass do this:
public class CustomClass {
List<Description> descriptions;
}
And that's it. Remember to create getters and setters because Jackson needs it.
You could try something like this:
public class DescriptionWrapper {
private Description descriptions;
public Description getDescriptions() {
return descriptions;
}
public void setDescriptions(Description descriptions) {
this.descriptions = descriptions;
}
}
public class Description {
private String desc1;
private NameValue desc2;
public String getDesc1() {
return desc1;
}
public void setDesc1(String desc1) {
this.desc1 = desc1;
}
public NameValue getDesc2() {
return desc2;
}
public void setDesc2(NameValue desc2) {
this.desc2 = desc2;
}
}
public class NameValue {
private String name;
private double val;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getVal() {
return val;
}
public void setVal(double val) {
this.val = val;
}
}