I'm having a null return using Gson.fromJson() and I don't understand why.
I'm calling an API that returns some data with this format:
{
"RealisedItems":{
"realisedItem":[
{
"actionItem1":1,
"actionItem2":"ITEM_ANSWER",
"actionItem3":"CREATE_ITEM",
"actionItem4":[
"XXXXXXX"
]
},
{
"actionItem1":2,
"actionItem2":"ITEM_ANSWER",
"actionItem3":"LINK_ITEM",
"actionItem5":"202007050000",
"actionItem4":[
"XXXXXXX"
]
}
]
}
}
Here's my objects to receive the data :
public class RealisedItems {
private List<RealisedItem> realisedItem = null;
public List<RealisedItem> getRealisedItem() {
return realisedItem;
}
public void setRealisedItem(List<RealisedItem> realisedItem) {
this.realisedItem = realisedItem;
}
}
And
public class RealisedItem {
private Long actionItem1;
private String actionItem2;
private String actionItem3;
private List<String> actionItem4 = null;
private String actionItem5;
public Long getActionItem1() {
return actionItem1;
}
public void setActionItem1(Long actionItem1) {
this.actionItem1 = actionItem1;
}
public String getActionItem2() {
return actionItem2;
}
public void setActionItem2(String actionItem2) {
this.actionItem2 = actionItem2;
}
public String getActionItem3() {
return actionItem3;
}
public void setActionItem3(String actionItem3) {
this.actionItem3 = actionItem3;
}
public List<String> getActionItem4() {
return actionItem4;
}
public void setActionItem4(List<String> actionItem4) {
this.actionItem4 = actionItem4;
}
public String getActionItem5() {
return actionItem5;
}
public void setActionItem5(String actionItem5) {
this.actionItem5 = actionItem5;
}
}
Using the debug mode, I can see by that the response object from this line : gson.fromJson(response, RealisedItems.class); contains the Json in String format that you can see above but my list is null after this. I'm using the same code for another response from a different service and I have my object filled with data.
From what I can see, in the fist "realisedItem" object, I have 4 items while in the second, I have 5. Can this cause this issue?
I tried to change the list to an array (RealisedItem[]) but it's not working either.
I also tried to use the #Expose with #SerializedName and changing Gson gson = new Gson(); to Gson gson = new GsonBuilder().create(); and Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create(); with the fifth item not having the #Expose annotation, but I'm still having my list null.
Can you please enlight me? Thanks!
Thanks to #Andreas, I realized I've made a mistake and used RealisedItems as root object. I just created a new object called ItemsOutput which contains RealisedItems field. I added a #SerializedName annotation to indicate it's called "RealisedItems" with an uppercase and changed my Gson.fromJson() call with the newly created object. It's working.
Thanks!
JSON Response from API :
{
"result":[
{
"ResultType":"SUCCESS"
}
]
}
After Converting to ResultClass.class :
{
"result":[
{
"resultType":null
}
]
}
Expected Output After Converting to ResultClass.class :
{
"result":[
{
"resultType":"SUCCESS"
}
]
}
I am integrating with third party API.I want to change property name while deserializing .I have tried #JsonProperty on filed getter and setter.But the value is not reflected in field resultType.
ResultClass.java
#JsonProperty("result")
List<TestClass> result = new ArrayList<>();
public List<TestClass> getResult() {
return result;
}
public void setResult(List<TestClass> result) {
this.result = result;
}
TestClass.java
#JsonProperty("ResultType")
private String resultType;
public String getResultType() {
return resultType;
}
public void setResultType(String resultType) {
this.resultType = resultType;
}
Note : I have tried JsonObject and it is working fine.I am using HttpClient and HttpResponse for making request.Jackson Version : 2.5.0
2 Solutions are available:
1. Make case-insensitive deserializing
Add this feature on your object mapper:
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
2. Serialize and deserialize with different property names
To change the name of the property ResultType to resultType, you should rather use both #JsonGetter and #JsonSetter:
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonSetter;
public class TestClass {
private String resultType;
#JsonGetter("resultType")
public String getResultType() {
return resultType;
}
#JsonSetter("ResultType")
public void setResultType(String resultType) {
this.resultType = resultType;
}
}
I'm trying to build dynamic json request in java to send to my c++ server. I'm using the GSON library.
This is my json example:
{
"nodes": {
"12131231231231241": {
"gToken": {
"token": "AABBCCDDEEFF99001122334455667788"
},
"objects": {
"WATER_CONTROL_1": "0"
}
},
"7682642342432423": {
"userAuthentication": {
"userEmail": "user#mail.com",
"userPassword": "userPassword"
},
"objects": {
"LIGHT_1_CONTROL": "1"
}
}
}
}
If you can see the nodes object is dynamic. Inside him i can have a lot of items (in the example i put two, representing by 12131231231231241 and 7682642342432423). Inside each item the authentication method can be different (by token, by email/password) and inside objects item i can have a lot of different dynamic items too.
The part to send to my c++ server, parse the JSON and do the all validations (authetication for example) is already done and working (i test this json example inside c++ string, encode to json and do the parse, get the all items,etc).
So my problem is to build my class to send the request with some struct to corresponding to this dynamic json.
I already implement some other class to send json to my server and its work because i already know the json expected and on other cases the json have a static/fixed content.
My class for this dynamic json:
public class MonitorControlGetRequestArgs implements SerializableJSON {
Nodes nodes;
public MonitorControlGetRequestArgs() {
nodes = new Nodes();
}
static class Nodes{
public Nodes(){
}
}
public static MonitorControlGetRequestArgs fromStringJson(String data){
try {
Gson gson = new Gson();
return gson.fromJson(data, MonitorControlGetRequestArgs.class);
}
catch(Exception e){
return null;
}
}
public static MonitorControlGetRequestArgs fromBytesJson(byte[] data){
if (data == null)
return null;
try {
String str = new String(data, "utf-8");
return fromStringJson(str);
}
catch (Exception e) {
return null;
}
}
#Override
public String toJsonString(){
try{
Gson gson = new Gson();
return gson.toJson(this);
}
catch(Exception e){
return null;
}
}
#Override
public byte[] toJsonBytes(){
try {
return this.toJsonString().getBytes("utf-8");
}
catch (Exception e){
return null;
}
}
}
I create a static class Nodes empty to show you. In my server c++ i receive the item nodes in json format, but now i have a lot of doubts how to build the struct inside nodes to corresponding to my dynamic json.
I hope you understand my doubts. If you don't understand something tell to me.
EDIT 1 - (try to use the example of Andriy Rymar)
I try to simulate this json:
{
"nodes": {
"1317055040393017962": {
"userAuthentication": {
"userEmail": "rr#rr.com",
"userPassword": "rr123"
}
}
}
}
My request class:
public class MonitorControlGetRequestArgs implements SerializableJSON
{
private final static String nodeTemplate = "\"%s\":%s";
List nodes = new ArrayList<>();
public MonitorControlGetRequestArgs(UserAuthentication userAuthentication)
{
JsonData jsonData = new JsonData();
jsonData.addNode(new Node("1317055040393017962", new NodeObject(userAuthentication)));
}
static class Node
{
private final String nodeName;
private final Object nodeBody;
public Node(String nodeName, Object nodeBody) {
this.nodeName = nodeName;
this.nodeBody = nodeBody;
}
public String getNodeName() {
return nodeName;
}
public Object getNodeBody() {
return nodeBody;
}
}
static class JsonData {
List<Node> nodes = new ArrayList<>();
public void addNode(Node node){
nodes.add(node);
}
}
static class NodeObject
{
UserAuthentication userAuthentication;
public NodeObject(UserAuthentication userAuthentication)
{
this.userAuthentication = userAuthentication;
}
}
public static MonitorControlGetRequestArgs fromStringJson(String data)
{
try
{
Gson gson = new Gson();
return gson.fromJson(data, MonitorControlGetRequestArgs.class);
}
catch(Exception e)
{
return null;
}
}
public static MonitorControlGetRequestArgs fromBytesJson(byte[] data)
{
if (data == null) return null;
try
{
String str = new String(data, "utf-8");
return fromStringJson(str);
}
catch (Exception e)
{
return null;
}
}
#Override
public String toJsonString()
{
try
{
Gson gson = new Gson();
return gson.toJson(this);
}
catch(Exception e)
{
return null;
}
}
#Override
public byte[] toJsonBytes()
{
try
{
return this.toJsonString().getBytes("utf-8");
}
catch (Exception e)
{
return null;
}
}
}
EDIT 2
I will try to explain better,i believe I was not totally explicit. My application java is a REST application that send json to my c++ server. In my server i receive the json, i do the parse, i do the validation, the operations, etc and return back to my java client the response in json too.
For example, imagine that my json request body (to create a new user for example) is something like this:
{
"userInformation": {
"name": "user name",
"age": 33
}
}
For this i don't have any doubts how to do (i already implement a lot of requests very similar). I can create a static class like this:
static class UserInfo
{
String name;
String age;
public UserInfo(String name, String age)
{
this.name = name;
this.age = age;
}
}
And inside a request class (very similar to a class like i copy before - MonitorControlGetRequestArgs) i create a new instance to my UserInfo
UserInfo userInformation = new UserInfo (name, age)
In this case its easy because the request json body is static. I already now that i have a userInformation section and inside i have a name and age. To create a list with userInfo (to create multiple users at same time for example) i already implement things like this.
But now, for this specific case i have this json:
{
"nodes": {
"12131231231231241": {
"gToken": {
"token": "AABBCCDDEEFF99001122334455667788"
},
"objects": {
"WATER_CONTROL_1": "0"
}
},
"7682642342432423": {
"userAuthentication": {
"userEmail": "user#mail.com",
"userPassword": "userPassword"
},
"objects": {
"LIGHT_1_CONTROL": "1"
"LIGHT_3_CONTROL": "0"
}
}
}
}
So in this case i have some problems. In these example i put two items (12131231231231241,7682642342432423) but the user can send more (3,4,5,50,100). In the other hand inside nodes i have two sections (12131231231231241,7682642342432423) but this numbers are some ids that i use in my app and i never know that ids the user will put. In last example ( userInformation ) its simple because i create a userInformation section because i already know that the user always put this section, it is static. In these new json request i dont know, because i never now what value he put, i only know that is a string. The authentication method i dont have problems to create. But other problem that i expected to have is in objects section, because the user can put to a lot of objects and i never know what is the key (in userInformation i know that the keys are always the name and age for example and only exits these two keys, i these new case i dont know what is the keys and what are the number of pair of keys/values he put).
EDIT 3 -
I implement this code and i could almost produce all the structure I need. I'm using the gson same.
Nodes nodes;
public MonitorControlGetRequestArgs(String userEmail, String userPassword, Map <String,String> objects)
{
nodes = new Nodes(userEmail, userPassword, objects);
}
static class Nodes
{
AuthenticationMethod authenticationMethod;
Map <String,String> objects;
public Nodes(String userEmail, String userPassword, Map <String,String> objects)
{
authenticationMethod = new AuthenticationMethod(userEmail, userPassword);
this.objects = objects;
}
}
The result json:
{
"nodes": {
"authenticationMethod": {
"userAuthentication": {
"userEmail": "user#mail.com",
"userPassword": "userPassword"
}
},
"objects": {
"aa": "aaaaaaaaaaaaa",
"bbbbbbb": "bbbbb",
"ccdd": "ccddccdd"
}
}
}
Know i only need to add some struct to support this json:
{
"nodes": {
"7682642342432423": {
"authenticationMethod": {
"userAuthentication": {
"userEmail": "user#mail.com",
"userPassword": "userPassword"
}
},
"objects": {
"0": "Hammersmith & City",
"1": "Circle",
"dasd": "dasda"
}
}
}
}
Note: The objects is a map, so i can put the number of objects string/string that i want. Know i need to do something to support the previous json with the 7682642342432423, 12131231231231241, etc, etc..
EDIT 4 - final
Map <String, Obj> nodes;
public MonitorControlGetRequestArgs(Map <String, Obj> nodes)
{
this.nodes = nodes;
}
static class Obj
{
AuthenticationMethod authenticationMethod;
Map <String,String> objects;
public Obj(String userEmail, String userPassword, Map <String,String> objects)
{
authenticationMethod = new AuthenticationMethod(userEmail, userPassword);
this.objects = objects;
}
}
Json that arrive in my server (like i want)
{
"nodes": {
"12131231231231241": {
"authenticationMethod": {
"userAuthentication": {
"userEmail": "user#mail.com",
"userPassword": "userPassword"
}
},
"objects": {
"aa": "aaaaaaaaaaaaa",
"bbbbbbb": "bbbbb",
"ccdd": "ccddccdd"
}
},
"777777777777777": {
"authenticationMethod": {
"userAuthentication": {
"userEmail": "user#mail.com",
"userPassword": "userPassword"
}
},
"objects": {
"aa": "aaaaaaaaaaaaa",
"bbbbbbb": "bbbbb",
"ccdd": "ccddccdd"
}
}
}
}
Here is improved code from previous example that is more flexible and has better serialization mechanism :
public class ForTestApplication {
public static void main(String[] args) {
NodeArray jsonContainer = new NodeArray(
new Node("nodes", new NodeArray(
new Node("12131231231231241", new NodeArray(
new Node("gToken",
new Node("token", "AABBCCDDEEFF99001122334455667788")),
new Node("objects", new NodeArray(
new Node("WATER_CONTROL_1", "0"),
new Node("WATER_CONTROL_2", "1")
)))),
new Node("7682642342432423", new NodeArray(
new Node("userAuthentication", new NodeArray(
new Node("userEmail","user#mail.com"),
new Node("userPassword","userPassword")
)),
new Node("objects", new NodeArray(
new Node("WATER_CONTROL_1", "0"),
new Node("WATER_CONTROL_2", "1")
))
))
)));
System.out.println(jsonContainer.toJSONString());
}
}
class NodeArray {
private static final String NODE_TEMPLATE = "\"%s\":%s";
private static final Gson gson = new Gson();
private List<Node> nodes = new ArrayList<>();
public NodeArray(Node... nodes){
addNode(nodes);
}
public void addNode(Node... node){
nodes.addAll(Arrays.asList(node));
}
public String toJSONString() {
return nodes.stream()
.map(node -> String.format(NODE_TEMPLATE, node.getNodeName(), getNodeBodyAsJSON(node)))
.collect(Collectors.joining(",", "{", "}"));
}
private String getNodeBodyAsJSON(Node node) {
if (node.getNodeBody() instanceof NodeArray) {
return ((NodeArray) node.getNodeBody()).toJSONString();
}
return gson.toJson(node.getNodeBody());
}
}
class Node {
private final String nodeName;
private final Object nodeBody;
public Node(String nodeName, Object nodeBody) {
this.nodeName = nodeName;
this.nodeBody = nodeBody;
}
public String getNodeName() {
return nodeName;
}
public Object getNodeBody() {
return nodeBody;
}
}
The output of such application is :
{"nodes":{"12131231231231241":{"gToken":{"nodeName":"token","nodeBody":"AABBCCDDEEFF99001122334455667788"},"objects":{"WATER_CONTROL_1":"0","WATER_CONTROL_2":"1"}},"7682642342432423":{"userAuthentication":{"userEmail":"user#mail.com","userPassword":"userPassword"},"objects":{"WATER_CONTROL_1":"0","WATER_CONTROL_2":"1"}}}}
Pretty view is :
NOTICE : this example use constructors to build complex structures but I highly recommend to use builder pattern for such case. Code will be clearer and better.
Here is example of what you need using Gson. But if you would like to use something else, for example OrgJson then the code will be more clear and without String templates.
public class ForTestApplication {
private final static String nodeTemplate = "\"%s\":%s";
public static void main(String[] args) {
JsonData jsonData = new JsonData();
jsonData.addNode(new Node("user-1", new TestObject(62, "James", "Gosling")));
jsonData.addNode(new Node("user-2", new TestObject(53, "James", "Hetfield")));
System.out.println(jsonData.toJSONStirng());
}
static class JsonData {
List<Node> nodes = new ArrayList<>();
public void addNode(Node node){
nodes.add(node);
}
public String toJSONStirng() {
Gson gson = new Gson();
return nodes.stream()
.map(node -> String.format(nodeTemplate, node.getNodeName(), gson.toJson(node.getNodeBody())))
.collect(Collectors.joining(",", "{", "}"));
}
}
static class Node {
private final String nodeName;
private final Object nodeBody;
public Node(String nodeName, Object nodeBody) {
this.nodeName = nodeName;
this.nodeBody = nodeBody;
}
public String getNodeName() {
return nodeName;
}
public Object getNodeBody() {
return nodeBody;
}
}
static class TestObject {
private int age;
private String firstName;
private String lastName;
public TestObject(int age, String firstName, String lastName) {
this.age = age;
this.firstName = firstName;
this.lastName = lastName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
}
Output :
{"user-1":{"age":62,"firstName":"James","lastName":"Gosling"},"user-2":{"age":53,"firstName":"James","lastName":"Hetfield"}}
Pretty view :
I have a JSON that looks like this:
{
"results": {
"exchange": [
"site.com",
{
"currency": "usd",
"last_traded": "2015.24"
}
]
}
}
How do I get the last_traded value?
I wrote some POJO for this, but I can't seem to find a way to get the key-value inside exchange array.
public class ExchangeContainer {
#Expose
private Results results;
public Results getResults() {
return results;
}
public void setResults(Results results) {
this.results = results;
}
#Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
}
public class Results {
#Expose
private List<String> exchange = new ArrayList<String>();
public List<String> getExchange() {
return exchange;
}
public void setExchange(List<String> exchange) {
this.exchange = exchange;
}
#Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
}
I'm using GSON to deserialize this JSON.
So in order for me to traverse through the model is:
ExchangeContainer response;
String rate = response.getResults().getExchange().get(1); // how to continue?
and I'm stuck.
Implement interface using implements JsonDeserializer in your class
and override deserialize method.
Example link - http://www.javacreed.com/gson-deserialiser-example/
As you have created list of Strings by
private List<String> exchange = new ArrayList<String>();
& setting another list in created list i.e., in exchange
public void setExchange(List<String> exchange)
When you get value by invoking line
String rate = response.getResults().getExchange().get(1);
it contains "last_traded": "2015.24" is it right ?
Now to get 2015.24, you have following choices :-
String[] split(":")
String substring(int beginIndex)
I hope this will solve your problem.
I am facing problem while deserializing to below entity using Javascript Serializer. Please help
JSON String:
{"AccountNo":0,"EmailAddress":"test#gmail.com","Destination_Prefernce":[{"Value":"Test Data"}]}
Java Code
public class EMailPreferenceEntity
{
private int _accountNo;
private string emailAddress;
private DestinationPreferences _destinationPrefernce = new DestinationPreferences();
public int AccountNo
{
get { return _accountNo; }
set { _accountNo = value; }
}
public string EmailAddress
{
get { return emailAddress; }
set { emailAddress = value; }
}
public DestinationPreferences Destination_Prefernce
{
get { return _destinationPrefernce; }
set { _destinationPrefernce = value; }
}
}
Handler File:
public class AjaxHandler : IHttpHandler, IRequiresSessionState
{
public void ProcessRequest (HttpContext context) {
string jsData = context.Request["Data"];
if (!string.IsNullOrEmpty(jsData))
{
JavaScriptSerializer ser = new JavaScriptSerializer();
EMailPreferenceEntity jsEntity = ser.Deserialize<EMailPreferenceEntity>(jsData);
}
}
Type erasure means your List will just become List after compilation so, when your http request arrives, it will try to deserialize List, and probably won't hit whatever you registered for List.
I'm not sure how your serializer handles it, but in Gson's case, you create a TypeToken out of the generic, so that the connection between type and serializer doesn't get lost after compilation.