Gson error: Expected a string but was BEGIN_ARRAY - java

My json:
{"code":200,"data":[{"xxx":"xxx","yyy":1234,"zzz":"56789"},{...}]}
I need Gson to take the data part in the shape of [{...}] and put it to simple String. But Gson keeps trying to parse it as an array and throws this JsonSyntaxException. Is it possible to get the result as I want it?
Gson fromJson call:
ParsedResponse parsedResponse = gson.fromJson(jsonString, ParsedResponse.class);
ParsedResponse class:
public class ParsedResponse {
#SerializedName("code")
private int code;
#SerializedName("data")
private String data;
private int statusCode;
// getters, setters
}
EDIT:
The system works when I have {...} in data, so why couldn't it work with [{...}]? I just need Gson to take the string [{...}] and put it to String variable.

Basically, no. Just put into Array and then convert to what you need.
Other approach is to see if you can over-ride some parser implementation of GSON.
Or write your own JSON to reflection library. :-).
*** Or, just write your own JSON parsing as your data format might be well-known to you and simply enough. :-)

Related

Convert String (http json) to Object in java (automatic)

I'm a beginner in programming, and I need some help. Is it possible to convert an HTTP (that returns a Json) automatic call to object in java? For example it reads the request, and when I call System.out.println (obj) it already returns me an OBJECT of this request, instead of String. Is it possible? If so, could you help me ... I already did the method to call the url and return string, but I need to return OBJECT, so I can compare with HashCode and Equals.
My code:
enter image description here
output:
{"header":{"messageId":"02938ec7-b2c3-4131-8ecf-3ad3a8509b41"},"body":{"products"
What I wanted: output
Informacoes [header=Header [messageId=66d22c00-bddc-4ea7-afbd-7c7225fcb914], body=Body
From what I can understand from your question, it looks like Gson might be useful. Gson is a library that allows you to convert between JSON and Java primitives/objects. Here's an example I just wrote:
class BagOfPrimitives {
private int value1 = 1;
private String value2 = "abc";
}
public static void main(String[] args) {
Gson gson = new Gson();
String json = "{\"value1\":1,\"value2\":\"abc\"}";
BagOfPrimitives obj = gson.fromJson(json, BagOfPrimitives.class);
}
This code converts the json {"value1":1,"value2":"abc"} into an object of the class BagOfPrimitives.
To add Gson to your project, go here, click "Downloads" at the top right, and click "jar". Then follow these instructions to add the jar file to your project. Then you should be able to write import com.google.gson.* at the top of your class and use Gson in your java code.

How can I deserialize a list of enums using Jackson JSON?

I'm working on a configuration system. I'd like to be able to load config values from a JSON file and have them "automagically" convert to the Java type I need. I'm using Jackson for the JSON parsing. For primitive types like floats and strings, it's no big deal, but I'm running into a snag with enums.
Let's say I have the following enum:
public enum SystemMode
{
#JsonProperty("Mode1")
MODE1("Mode1"),
#JsonProperty("Mode2")
MODE2("Mode2"),
#JsonProperty("Mode3")
MODE3("Mode3");
private final String name;
private SystemMode(String name)
{
this.name = name;
}
#Override
#JsonValue
public String toString()
{
return this.name;
}
}
Now, let's say I want to represent a list of values of this enum for a given config variable using the following JSON representation:
{
"Project" : "TEST",
"System" : {
"ValidModes" : ["Mode1", "Mode2"]
}
}
And I'd like to be able to do something like the following:
ArrayList<SystemMode> validModes = (ArrayList<SystemMode>) configurator.getConfigValue("/System/ValidModes");
For reference, my configurator class's getConfigValue method is essentially a thin wrapper over the Jackson JSON parsing:
public Object getConfigValue(String JSON_String)
{
JsonNode node = JsonNodeFactory.instance.objectNode().at(JSON_String);
return objectMapper.convertValue(node, Object.class);
}
(The real method has some exception checking that has been omitted for clarity).
Now, when I call the above, Jackson correctly deduces that I want an ArrayList and fills it. However, instead of getting an ArrayList of SystemMode enums, I get an ArrayList of Strings and immediately throw an exception when I attempt to use the list. I have tried several different ways of representing the data to no avail. It seems no matter what I try, Jackson wants to return a list of strings instead of a list of enums.
So my question is this:
How can I make Jackson (version 2.9.4) JSON properly deserialize a list of enum values in a way that is compatible with my single "Object getConfigValue()" method?
The following will provide the correct binding for your enum.
public List<SystemMode> getConfigValue(String path)
{
JsonNode node = JsonNodeFactory.instance.objectNode().at(path);
return objectMapper.convertValue(node, new TypeReference<List<SystemMode>>(){});
}
The second option is to convert the list of String yourself, for example:
List<SystemMode> result = jsonResult.stream().map(SystemMode::valueOf).collect(Collectors.toList());
Third option:
public <T>List<T> getConfigValue(String path, Class<T> type)
{
JsonNode node = JsonNodeFactory.instance.objectNode().at(path);
CollectionType toType =
objectMapper.getTypeFactory().constructCollectionType(List.class, type);
return objectMapper.convertValue(node, toType);
}

Gson serialization depending on field value

I have a POJO that is similar to:
public class MyGsonPojo {
#Expose
#SerializedName("value1")
private String valueOne;
#Expose
#SerializedName("value2")
private boolean valueTwo;
#Expose
#SerializedName("value3")
private int valueThree;
// Getters and other stuff here
}
The issue is that this object has to be serialized into a json body for a call
to the server. Some fields are optional for the request and if I even send it with default and null values, the API responds differently (Unfortunately changing the api is not an option).
So basically I need to exclude fields from serialization if any of them is set to a default value. For example if the field valueOne is null the resulting json should be:
{
"value2" : true,
"value3" : 2
}
Any idea how to make this a painless effort? I wouldn't want to build the json body manually.
Any help would be great. Thank you in advice.
Steps to follow:
Convert the JSON String into Map<String,Object> using Gson#fromJson()
Iterate the map and remove the entry from the map which are null
Form the JSON String back from the final map using Gson#toJson().
I have already posted the sample code in the same context here:
Remove empty collections from a JSON with Gson
Option 1) Use a TypeAdapter, see accepted answer here:
Option 2) If using Jackson instead of gson is a possibility, you can annotate/serialize on getters instead of on fields, and put your logic for returning
whatever you need for "default values" in your getters.
//won't get serialized because it's private
private String valueOne;
...
#JsonSerialize
String getValueOne(){
if (valueOne == null) return "true"
else...
}
You could also use a single #JsonInclude(Include.NON_NULL) or #JsonInclude(Include.NON_EMPTY) annotation at the top of your class to prevent any null or empty fields from being serialized.

Mapping JSON to Java objects with different keywords

My company has a webserver API that provides search results in JSON format. I'm responsible for developing an Android app that consumes that API, and I have made some classes that model the objects in the JSON responses.
For the sake of habit and my own preference, I use to write my code in English only. However, most of the JSON keys are not in English. This way, I cannot readily use GSON to convert the JSON strings into Java Objects -- at least that is what I think.
I was wondering if there is any way to reference just once per class the connection between the JSON key and their corresponding instance variables in the code. In a way that after referenced, I could simply instantiate objects from JSON and create JSON strings from objects.
Is that possible?
Example:
// Java code
class Model {
String name;
Integer age;
}
// JSON with keys in Portuguese
{
"nome" : "Mark M.", # Key "nome" matches variable "name"
"idade" : 30 # Key "idade" matches variable "age"
}
Use the #SerializedName annotation.
Here is an example of how this annotation is meant to be used:
public class SomeClassWithFields {
#SerializedName("name") private final String someField;
private final String someOtherField;
public SomeClassWithFields(String a, String b) {
this.someField = a;
this.someOtherField = b;
}
}
The following shows the output that is generated when serializing an instance of the above example class:
SomeClassWithFields objectToSerialize = new SomeClassWithFields("a", "b");
Gson gson = new Gson();
String jsonRepresentation = gson.toJson(objectToSerialize);
System.out.println(jsonRepresentation);
===== OUTPUT =====
{"name":"a","someOtherField":"b"}
Source: SerializedName Javadocs

Parsing JSON array with gson

I am having trouble parsing my JSON which i get from javascript.
The format of JSON is this:
[{"positions":[{"x":50,"y":50},{"x":82,"y":50},{"x":114,"y":50},{"x":146,"y":50}]},{"positions":[{"x":210,"y":50},{"x":242,"y":50},{"x":274,"y":50}]}]
So far i have been able to get this far:
{"positions":[{"x":50,"y":50},{"x":82,"y":50},{"x":114,"y":50},{"x":146,"y":50}]}
But i also need to now create a class with those positions. I havnt been working on the class, since i tried printing out the output first, but i am unable to break it down further. I am getting this error message:
java.lang.IllegalStateException: This is not a JSON Array.
And my code is this:
JsonParser parser = new JsonParser();
String ships = request.getParameter("JSONships");
JsonArray array = parser.parse(ships).getAsJsonArray();
System.out.println(array.get(0).toString());
JsonArray array2 = parser.parse(array.get(0).toString()).getAsJsonArray();
System.out.println(array2.get(0).toString());
I have also tried to do it this way:
Gson gson = new Gson() ;
String lol = (gson.fromJson(array.get(0), String.class));
System.out.println(lol);
In which case i get:
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected STRING but was BEGIN_OBJECT
In the end, i want to loop through positions, creating class for each "positions", which contains a List with another class Position, which has the int x, y.
Thank you for your time.
Define your classes and you will get everything you need using gson:
public class Class1 {
private int x;
private List<Class2> elements;
}
And the inner class:
public class Class2 {
private String str1;
private Integer int2;
}
Now you can parse a json string of the outer class just like that:
gson.fromJson(jsonString, Class1.class);
Your error while using Gson is that you try to parse a complex object in String, which is not possible.

Categories