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!
Related
To the best of my understanding, Jackson will
serialize a public instance variable to the variable name
public List<String> myStrings = new ArrayList<>();
serializes to
{ 'myStrings' : [ ... ] }
serialize a private instance variable to the variable name if it has a public getter named getVariable():
private List<String> myStrings = new ArrayList<>();
public List<String> getMyStrings() { return myStrings; }
serializes similar to
{ 'myStrings' : [ ... ] }
However, what I am trying to achieve is to serialize it to a String (instead of array of Strings) based on another method, but keep the JSON key (based on #JsonInclude(JsonInclude.Include.NON_NULL) suppressing the original accessor in some cases
#JsonInclude(JsonInclude.Include.NON_NULL)
private boolean firstStringOnly = true;
private List<String> myStrings = new ArrayList<>();
public List<String> getMyStrings() { return firstStringOnly ? null: myStrings; }
public String getFirstString() { return firstStringOnly ? myStrings.get(0) : null; }
Desired JSON serialization:
For firstStringOnly==true: { 'myStrings' : 'first_String' } (using getFirstString())
For firstStringOnly==false: { 'myStrings' : [ ... ] } (using getMyStrings())
Is this possible to do? I'm specifically looking to avoid using custom serializers, and do this via annotations only.
You can assume a reasonably recent version of Jackson and Java 8.
Just to re-iterate, the question constraints are:
* NO custom serializer
* Both use cases produce the same JSON key
You can generalize getMyStrings() method and make it return Object. And inside check the flag and return first value or all values. Here is my sample
public class tst {
private static class YourObject {
private boolean firstStringOnly;
private List<String> myStrings = new ArrayList<>();
public YourObject(boolean firstStringOnly) {
this.firstStringOnly = firstStringOnly;
this.myStrings.add("str1");
this.myStrings.add("str2");
}
public Object getMyStrings(){
return firstStringOnly ? myStrings.get(0) : myStrings;
}
}
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writeValueAsString(new YourObject(true)));
System.out.println(mapper.writeValueAsString(new YourObject(false)));
}
}
The output is
{"myStrings":"str1"}
{"myStrings":["str1","str2"]}
EDIT: Sorry, i have misread your initial question. I assume you want to keep both of the typed getters. Would this work for you?
public class TestClass {
private boolean firstStringOnly = true;
private List<String> myStrings = new ArrayList<>();
#JsonIgnore
public boolean isFirstStringOnly() {
return firstStringOnly;
}
public void setFirstStringOnly(boolean firstStringOnly) {
this.firstStringOnly = firstStringOnly;
}
#JsonIgnore
public List<String> getMyStrings() {
return firstStringOnly ? null : myStrings;
}
#JsonIgnore
public String getFirstString() { return firstStringOnly ? myStrings.get(0) : null; }
#JsonProperty("myStrings")
public Object getMyStringsForSerialization() {
return firstStringOnly ? getFirstString() : getMyStrings();
}
public void setMyStrings(List<String> myStrings) {
this.myStrings = myStrings;
}
I'm trying to deserialize a JSON which containes a String and a list of objects in my Spring web application.
JSON
[
{
"jsonrpc":"2.0",
"result":[
{
"event":{
"id":"27809810",
"name":"Spezia v Trapani",
"countryCode":"IT",
"timezone":"Europe/London",
"openDate":"2016-05-28T16:30:00.000Z"
},
"marketCount":13
},
{
"event":{
"id":"27811083",
"name":"Torino U19 v Atalanta U19",
"countryCode":"IT",
"timezone":"Europe/London",
"openDate":"2016-05-29T16:15:00.000Z"
},
"marketCount":18
},
...
]
My classes are:
ListEventsResponse class
public class ListEventsResponse {
private String jsonrpc;
private List<ListEventsResult> result;
public ListEventsResponse() { }
public String getJsonrpc() {
return jsonrpc;
}
public void setJsonrpc(String jsonrpc) {
this.jsonrpc = jsonrpc;
}
public List<ListEventsResult> getResult() {
return result;
}
public void setResult(List<ListEventsResult> result) {
this.result = result;
}
}
ListEventsResult class
public class ListEventsResult {
private Event event;
private int marketCount;
public ListEventsResult() { }
public Event getEvent() {
return event;
}
public void setEvent(Event event) {
this.event = event;
}
public int getMarketCount() {
return marketCount;
}
public void setMarketCount(int marketCount) {
this.marketCount = marketCount;
}
}
I have also Event class, composed by 5 String (id, name, etc.).
Controller
[...]
ListEventsResponse listEvents = new Gson().fromJson(response.toString(), ListEventsResponse.class);
List<ListEventsResult> eventsList = listEvents.getResult();
return new ModelAndView("page", "eventsList", eventsList);
My .jsp page
[...]
<c:forEach items="${eventsList}" var="listEventsResult">
Match: <c:out value="${listEventsResult.name}"/>
</c:forEach>
[...]
My code runs and doesn't give any error, but no match is shown on my page, in fact listEvents doesn't contains any object.
I can't understand how to deserialize properly the list of objects, so my question is: which logic is behind the deserialization of a json which contains a list of objects?
I post my code just to explain better my problem.
As you have a Json Array as response , you need to deserialize like below
Gson gson = new Gson();
Type type = new TypeToken<List<ListEventsResponse>>(){}.getType();
List<ListEventsResponse> events = (List<ListEventsResponse>) gson.fromJson(response.toString(), type);
Currently I have form like below:
public class Form {
private String listOfItems;
public String getListOfItems() {
return listOfItems;
}
public void setListOfItems(String listOfItems) {
this.listOfItems= listOfItems;
}
}
For instanse listOfItems equals to the following string "1,2,3".
The goal is to serialize this form to following format:
{
"listOfItems": [1, 2, 3]
}
It would be good to know how to correctly do such thing? As I know it is possible to create some custom serializer then mark appropriate getter method with it, like this #JsonSerialize(using = SomeCustomSerializer).
But not sure whether it is correct approach, probably any default implementations already exist.
If you can edit your Form class:
public class Form {
private String listOfItems;
public String getListOfItems() {
return listOfItems;
}
public void setListOfItems(String listOfItems) {
this.listOfItems = listOfItems;
}
#JsonProperty("listOfItems")
public List<Integer> getArrayListOfItems() {
if (listOfItems != null) {
List<Integer> items = new ArrayList();
for (String s : listOfItems.split(",")) {
items.add(Integer.parseInt(s)); // May throw NumberFormatException
}
return items;
}
return null;
}
}
By default Jackson looks for getters for serializing. You can override this by using #JsonProperty annotation.
ObjectMapper mapper = new ObjectMapper();
Form form = new Form();
form.setListOfItems("1,2,3");
System.out.print(mapper.writeValueAsString(form));
Outputs:
{"listOfItems":[1,2,3]}
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.