If I try to deserialize my json:
String myjson = "
{
"intIdfCuenta":"4720",
"intIdfSubcuenta":"0",
"floatImporte":"5,2",
"strSigno":"D",
"strIdfClave":"FT",
"strDocumento":"1",
"strDocumentoReferencia":"",
"strAmpliacion":"",
"strIdfTipoExtension":"IS",
"id":"3"
}";
viewLineaAsiento asiento = gson.fromJson(formpla.getViewlineaasiento(),viewLineaAsiento.class);
I get this error:
com.google.gson.JsonSyntaxException: java.lang.NumberFormatException: For input string: "5,2"
How can I parse "5,2" to Double???
I know that if I use "floatImporte":"5.2" I can parse it without any problem but I what to parse "floatImporte":"5,2"
Your JSON is in first place bad. You shouldn't be representing numbers as strings at all. You should basically either have all String properties in your ViewLineaAsiento Java bean object representation as well, or to remove those doublequotes from JSON properties which represent numbers (and fix the fraction separator to be . instead of ,).
If you're absolutely posisive that you want to continue using this bad JSON and fix the problem by a workaround/hack instead of fixing the problem by its roots, then you'd need to create a custom Gson deserializer. Here's a kickoff example:
public static class BadDoubleDeserializer implements JsonDeserializer<Double> {
#Override
public Double deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException {
try {
return Double.parseDouble(element.getAsString().replace(',', '.'));
} catch (NumberFormatException e) {
throw new JsonParseException(e);
}
}
}
You can register it via GsonBuilder#registerTypeAdapter() as follows:
Gson gson = new GsonBuilder().registerTypeAdapter(Double.class, new BadDoubleDeserializer()).create();
ViewLineaAsiento asiento = gson.fromJson(myjson, ViewLineaAsiento.class);
Related
I have a Java POJO
public class TagBean {
private String type;
private String id;
public TagBean(String type, String id) {
this.type = type;
this.id = id;
}
// getters
// setters
}
I'm building pojo's and adding them to a List, as
....
List<TagBean> channelsList = new ArrayList<>();
List<TagBean> showsList = new ArrayList<>();
for each <business logic> {
if value=channels {
channelsList.add(new TagBean(...));
}
if value=shows {
showsList.add(new TagBean(...));
}
}
Gson gson = new GsonBuilder().create();
JsonObject tjsonObject = new JsonObject();
tjsonObject.addProperty("channels", gson.toJson(channelsList));
tjsonObject.addProperty("shows", gson.toJson(showsList));
JsonObject mainjsonObject = mainjsonObject.add("tags", tjsonObject);
return mainjsonObject;
My output is:
{
"tags": {
"channels": "[{\"type\":\"channel\",\"id\":\"channel\",\"name\":\"Channel\",\"parent\":\"SXM\"}]",
"shows": "[{\"type\":\"shows\",\"id\":\"shows\",\"name\":\"Shows\",\"parent\":\"SXM\"},{\"type\":\"shows\",\"id\":\"howard\",\"name\":\"Howard Stern\",\"parent\":\"shows\"},{\"type\":\"shows\",\"id\":\"howardstern\",\"name\":\"Howard Stern\",\"parent\":\"howard\"}]",
"sports": "[]"
}
}
How can i remove the backslashes? So the output is like:
{
"tags": {
"channels": " [{"type":"channel","id":"channel","name":"Channel","parent":"SXM"}]",
"shows": "[{"type":"shows","id":"shows","name":"Shows","parent":"SXM"},{"type":"shows","id":"howard","name":"Howard Stern","parent":"shows"}....
There were few other posts, but none explained this.
The problem is caused by this:
tjsonObject.addProperty("channels", gson.toJson(channelsList));
What that is doing is converting channelsList to a string containing a representation of the list in JSON, then setting the property to that string. Since the string contains JSON meta-characters, they must be escaped when the strings are serialized ... a second time.
I think that you need to do this instead:
tjsonObject.add("channels", gson.toJsonTree(channelsList));
That should produce this:
{
"tags": {
"channels":
[{"type":"channel","id":"channel","name":"Channel","parent":"SXM"}],
"shows":
[{"type":"shows","id":"shows","name":"Shows","parent":"SXM"},
{"type":"shows","id":"howard","name":"Howard Stern","parent":"shows"}
....
That is slightly different to what your question asked for, but it has the advantage of being syntactically valid JSON!
String mainJsonStr = mainjsonObject.toString();
mainJsonStr = mainJsonStr.replace("\\\\", ""); //replace the \
System.out.println(mainJsonStr);
The problem is that gson.toJson returns a String, and
tjsonObject.addProperty("channels", gson.toJson(channelsList));
this will add channels as a string and not as a JSON object.
One possible solution is to convert the string returned from gson.toJson to JSON object first then add it to the parent JSON object like
Gson gson = new GsonBuilder().create();
JsonObject tjsonObject = new JsonObject();
tjsonObject.put("channels", new JsonObject(gson.toJson(channelsList)));
tjsonObject.put("shows", new JsonObject(gson.toJson(showsList)));
this will treat channels and shows as JSON object
All strings in java have to escape quotes in them. So jsonInString should have slashes in it. When you output jsonInString though it shouldn't have the quotes. Are you looking at it in a debugger or something?
Just parse json directly and check - will get the output
above solution is not working anymore since GSON 2.8.*
use gson.toJsonTree(jsonText).getAsString(); instead
I tried to convert following JSON string into Array and got following error:
Exception in thread "AWT-EventQueue-0" java.lang.NoClassDefFoundError:
org/apache/commons/logging/LogFactory at
net.sf.json.AbstractJSON.(AbstractJSON.java:54) at
net.sf.json.util.CycleDetectionStrategy.(CycleDetectionStrategy.java:36)
at net.sf.json.JsonConfig.(JsonConfig.java:65) at
net.sf.json.JSONSerializer.toJSON(JSONSerializer.java:84)
JSON:
[
{
"file_name":"1.xml",
"file_ext":"application/octet-stream",
"sr_no":"0.1",
"status":"Checked ",
"rev":"1",
"locking":"0"
},
{
"file_name":"2.xml",
"file_ext":"json/octet-stream",
"sr_no":"0.2",
"status":"Not Checked ",
"rev":"2",
"locking":"1"
},
{
"file_name":"3.xml",
"file_ext":"application/json-stream",
"sr_no":"0.3",
"status":"Checked ",
"rev":"1",
"locking":"3"
},
{
"file_name":"4.xml",
"file_ext":"application/octet-stream",
"sr_no":"0.4",
"status":"Checked ",
"rev":"0.4",
"locking":"4"
}
]
Code:
JSONArray nameArray = (JSONArray) JSONSerializer.toJSON(output);
System.out.println(nameArray.size());
for(Object js : nameArray)
{
JSONObject json = (JSONObject) js;
System.out.println("File_Name :" +json.get("file_name"));
}
I know the question is about converting JSON String to Java Array, but I would like to also answer about how to convert the JSON String to an ArrayList using the Gson Library.
Since I spend a good amount of time in solving this, I hope my solution may help others.
My JSON string looks similar to this one -
I had an object named StockHistory, and I wanted to convert this JSON into an ArrayList of StockHistory.
This is how my StockHistory class looked -
class StockHistory {
Date date;
Double open;
Double high;
Double low;
Double close;
Double adjClose;
Double volume;
}
The code that I used to convert the JSON Array to the ArrayList of StockHistory is as follows -
Gson gson = new Gson();
Type listType = new TypeToken< ArrayList<StockHistory> >(){}.getType();
List<StockHistory> history = gson.fromJson(reader, listType);
Now if you are reading your JSON from a file, the reader's initialization would be -
Reader reader = new FileReader(fileName);
and if you are just converting a string to JSON object then, the reader's initialization would simply be -
String reader = "{ // json String }";
Hope that helps. Cheers!!!
You can create a java class with entities are: file_name, file_ext, sr_no, status, rev, locking in string type.
public class TestJson {
private String file_name, file_ext, sr_no, status, rev, locking;
//get & set
}
}
Then you call:
public static void main(String[] args) {
String json = your json string;
TestJson[] respone = new Gson().fromJson(json, TestJson[].class);
for (TestJson s : respone) {
System.out.println("File name: " + s.getFile_name());
}
}
So, you have a list of object you want.
Firstly I have to say your question is quite "ugly" and next time please improve your question's quality.
Answer:
Try to use com.fasterxml.jackson.databind.ObjectMapper
If you have a java class to describe your items in the list:
final ObjectMapper mapper = new ObjectMapper();
YourClass[] yourClasses = mapper.readValue(YourString, YourClass[].class);
Then convert the array to a List.
If you don't have a java class, just you LinkedHashMap instead.
I want to parse below given data in to some java object, but I am not able to parse. String is as follows -
{\"objectsTree\":\"{\"Address\":[],\"Customer\":[\"Address\"]}\",\"objectsSequence\":\"[\"Customer\",\"Address\"]\"}
I have tried parsing this into HashMap and HashMap
but this is returning malformed JSON exception, and that is making sense, because of too many double quotes objects are ending abruptly. I want to parse this as follows-
{
"objectsTree":"{"Address":[],"Customer":["Address"]}",
"objectsSequence":"["Customer","Address"]"
}
here you can see that objectsTree is one object against one string and objectSequence is another. to be specific object tree is supposed to be a treemap , object sequence is supposed to be a ArrayList.
Any Idea how should I proceed.
code update-
package org.syncoms.backofficesuite.controller;
import java.util.HashMap;
import com.google.gson.Gson;
public class Test {
public static void main(String[] args) {
//String json = "{\"Success\":true,\"Message\":\"Invalid access token.\"}";
String json ="{\"objectsTree\":\"{\"Address\":[],\"Customer\":[\"Address\"]}\",\"objectsSequence\":\"[\"Customer\",\"Address\"]\"}";
Gson jsonParser = new Gson();
#SuppressWarnings("unchecked")
HashMap<String,Object> jo = (HashMap<String,Object>) jsonParser.fromJson(json, HashMap.class);
System.out.println(jo);
//Assert.assertNotNull(jo);
//Assert.assertTrue(jo.get("Success").getAsString());
}
}
the error which I am getting -
Exception in thread "main" com.google.gson.JsonParseException: Failed parsing JSON source: java.io.StringReader#201644c9 to Json
at com.google.gson.JsonParser.parse(JsonParser.java:59)
at com.google.gson.Gson.fromJson(Gson.java:443)
at com.google.gson.Gson.fromJson(Gson.java:396)
at com.google.gson.Gson.fromJson(Gson.java:372)
at org.syncoms.backofficesuite.controller.Test.main(Test.java:16)
Caused by: com.google.gson.ParseException: Encountered " <IDENTIFIER_SANS_EXPONENT> "Address "" at line 1, column 19.
Was expecting one of:
"}" ...
"," ...
The main issue here is that the input is simply not a valid JSON String, and no JSON parser is going to accept it. the doulbe qoutes have to be escaped.
a Valid JSON String is as follows:
String jsonInput = "{\"objectsTree\":\"{\\\"Address\\\":[],\\\"Customer\\\":[\\\"Address\\\"]}\",\"objectsSequence\":\"[\\\"Customer\\\",\\\"Address\\\"]\"}";
and this can be parsed using, for instance, Jackson:
ObjectMapper om = new ObjectMapper();
TypeFactory tf = om.getTypeFactory();
JavaType mapType = tf.constructMapType(HashMap.class, String.class, String.class);
Map<String, String> map = (Map<String, String>)om.readValue(jsonInput, mapType);
System.out.println(map);
Printout is:
{objectsSequence=["Customer","Address"], objectsTree={"Address":[],"Customer":["Address"]}}
There are multiple ways you could do that.
Firstly, if your data has always the same format you can simply create some methods which will create your TreeMap and ArrayList as required. You can do everything you want with String.replace(), StringTokenizer, matcher pattern. You can split your data into tokens and based on your needs place them in your required data structure. I find this way quite efficient and once you get to know better how to parse data and extract what you need, you can use this in many other examples.
If your data is formatted in JSON then there might be even easier ways of parsing it.You can decode it as Java object quite easy.
JSON string is not well formed one. Try as below
{
"objectsTree":{"Address":[],"Customer":["Address"]},
"objectsSequence":["Customer","Address"]
}
JSON key is always string &
JSON values can be:
•A number (integer or floating point)
•A string (in double quotes)
•A Boolean (true or false)
•An array (in square brackets)
•An object (in curly braces)
•null.
See the below code with well formed string and its output
String a = "{\r\n" +
"\"objectsTree\":{\"Address\":[],\"Customer\":[\"Address\"]},\r\n" +
"\"objectsSequence\":[\"Customer\",\"Address\"]\r\n" +
"}";
ObjectMapper mapper = new ObjectMapper();
HashMap<String,Object> jo = (HashMap<String,Object>) mapper.readValue(a, HashMap.class);
System.out.println("result: "+ jo);
result: {objectsTree={Address=[], Customer=[Address]}, objectsSequence=[Customer, Address]}
with your json string
String json ="{\"objectsTree\":\"{\"Address\":[],\"Customer\":[\"Address\"]}\",\"objectsSequence\":\"[\"Customer\",\"Address\"]\"}";
ObjectMapper mapper = new ObjectMapper();
HashMap<String,Object> jo = (HashMap<String,Object>) mapper.readValue(json, HashMap.class);
System.out.println("result: "+ jo);
error :
Exception in thread "main" org.codehaus.jackson.JsonParseException: Unexpected character ('A' (code 65)): was expecting comma to separate OBJECT entries
at [Source: java.io.StringReader#77d2b01b; line: 1, column: 20]
at org.codehaus.jackson.JsonParser._constructError(JsonParser.java:943)
In your json string, for key objectsTree, the value is started with \" and its matching \" is closed before string Address. This is causing the parse error.
"{\"Address
The other two answers also saying that your json string is in invalid format.
I also added the supported json values for your reference.
If you change to correct format, any json parser will work,
When I use the following piece of code in Android:
// convert JSON string to a List of Product objects
Type listType = new TypeToken<List<Product>>(){}.getType();
p = (List<Product>)new Gson().fromJson(json, listType);
It will convert:
[{"$id":"1","ProductId":17,"Name":"Product1","Price":1.49,"Visible":true},
{"$id":"2","ProductId":19,"Name":"Product2","Price":3.89,"Visible":true},
{"$id":"3","ProductId":20,"Name":"Product3","Price":0.32,"Visible":true}]
To three Product objects with the fields int ProductId, String Name, double Price, boolean Visible, and perhaps some other fields.
When I try the same with Orders (which contains a C# DateTime in the JSON) it fails with a JsonSyntaxException : 2014-05-13T00:00:00
So, my question: How can I successfully convert a JSON String containing a Date-String (2014-05-13T00:00:00), to a Java.util.Date object?
I did try the following:
// convert JSON string to a List of Order objects
Type listType = new TypeToken<List<Order>>(){}.getType();
Gson gson = new GsonBuilder().setDateFormat(DateFormat.FULL).create();
o = (List<Order>)gson.fromJson(json, listType);
and
// convert JSON string to a List of Order objects
Type listType = new TypeToken<List<Order>>(){}.getType();
Gson gson = new GsonBuilder().setDateFormat(DateFormat.FULL, DateFormat.FULL).create();
o = (List<Order>)gson.fromJson(json, listType);
but both didn't work.
NOTE: I Googled a bit and most solutions use serializers & deserializers in both the Java code and used API. But since I can't modify my JSON send from my C# Web API, this isn't an option for me. I can only add things at the receiver's end (my Android App).
PS: I might have a solution, though it's a bit extra work & contains a potentially slowing for-loop: I change the Date Date in my Order-class to String Date (so the Gson parsing will put it in that String-field), then add a Date mDate and after Gson has parsed the complete JSON-array of Orders, I parse the Dates to mDates in a for-loop.. Still, this solution is pretty inefficient, so if anyone know how to do it within GsonBuilder itself I would appreciate it.
Thanks in advance for the responses.
Ok, I was close, but made a small (and pretty obvious) mistake..
Instead of:
Gson gson = new GsonBuilder().setDateFormat(DateFormat.FULL, DateFormat.FULL).create();
I need to use:
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss").create();
EDIT:
I now use a deseralizer as well, but only in my Android part. The reason why I changed it is as follows:
When I had a differently formatted date or a date that was null, I would get a JsonParseException on the entire JSON, so none of my Order-Objects were created.
Now that I use this seralizer and a Date appears to be of an invalid format or null, it just makes that Date in the Order-object null, but still converts everything as it should with a resulting Order-list.
Code:
try{
// Convert JSON-string to a List of Order objects
Type listType = new TypeToken<ArrayList<Order>>(){}.getType();
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH);
#Override
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
try{
return df.parse(json.getAsString());
}
catch(ParseException ex){
return null;
}
}
});
Gson dateGson = gsonBuilder.create();
orders = dateGson.fromJson(json, listType);
}
catch(JsonParseException ex){
ex.printStackTrace();
}
I parse server JSON response with GSON library. Backend guys sometimes tell me: "We can't specify variable type in JSON for some reason" (old php, they don't know how to do it and so on and so forth).
GSON likes strong typing in its object model. So I can't parse Object as String.
GSON wait for:
{
"service":{
"description":null,
"name":"Base",
"id":"4c7a90410529"
}
}
But it gets (empty data):
"service": ""
And I get
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1396
What is the best practice to parse such response?
Another question:
How can I build object, it can recognize Integer variable which returned from time to time as Integer or as String? The same server side issue.
"data": "1"
or
"data": 1
I know - we should use specific types in Java. But sometime it is worth to make concessions,
Thanks
EDIT:
My solution based on Java Developer's answer.
ServiceDeserializer class deserialize every object depending on its internal value.
public class ServiceDeserializer implements JsonDeserializer<ServiceState>{
#Override
public ServiceState deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
String name = "";
String uuid = "";
String description = "";
if (json.isJsonObject()) {
JsonObject obj = json.getAsJsonObject();
if (!obj.get("name").isJsonNull()) {
name = obj.get("name").getAsString();
}
if (!obj.get("uuid").isJsonNull()) {
uuid = obj.get("uuid").getAsString();
}
if (!obj.get("description").isJsonNull()) {
description = obj.get("description").getAsString();
}
}
return new ServiceState(name, uuid, description);
}
}
And my GSON constructor with type adapter for ServiceState.
Gson gson = new GsonBuilder()
.registerTypeAdapter(ServiceState.class, new ServiceDeserializer())
.create();
You need to scrape the JSON response before trying to deserialize it into your Response Java object. You can make use of Java org.json parser to verify that service object actually exists and fix it otherwise.
String json = "{\"service\":{\r\n" +
" \"description\":null,\r\n" +
" \"name\":\"Base\",\r\n" +
" \"id\":\"4c7a90410529\"\r\n" +
"}}";
String json2 = "{\"service\":\"\"}";
JSONObject root = new JSONObject(json);
// JSONObject root = new JSONObject(json2);
if (root.optJSONObject("service") == null) {
root.put("service", new JSONObject());
}
Gson gson = new Gson();
Response response = gson.fromJson(root.toString(), Response.class);
System.out.println(response.getService());
Output :
// for JSONObject root = new JSONObject(json);
Service [id=4c7a90410529, name=Base, description=null]
// for JSONObject root = new JSONObject(json2);
Service [id=null, name=null, description=null]
Secondly, Gson is smart enough to do simple conversions like String to Integer etc. So, deserializing such JSON properties shouldn't give you any troubles.
System.out.println(gson.fromJson("10", Integer.class)); // 10
System.out.println(gson.fromJson("\"20\"", Integer.class)); // 20
If you want to stick with strictly gson you can provide a custom deserializer. Since we know that service is either a property of the base json string or embedded within some other property, we can use the deserializer to step-wise parse out the offending components and handle them accordingly.
public class MyJsonDeserializer implements JsonDeserializer<YourParsedData> {
#Override
public YourParsedData deserialize(final JsonElement je, final Type type, final JsonDeserialization Context jdc) throws JsonParseException
{
final JsonObject obj = je.getAsJsonObject(); //our original full json string
final JsonElement serviceElement = obj.get("service");
//here we provide the functionality to handle the naughty element. It seems emtpy string is returned as a JsonPrimitive... so one option
if(serviceElement instanceOf JsonPrimitive)
{
//it was empty do something
}
return YourParsedData.create(); //provide the functionality to take in the parsed data
}
}
The custom deserializer would be called as follows:
final Gson gson = new GsonBuilder().registerTypeAdapter(YourParsedData.class, new MyJsonDeserializer()).create();
gson.fromJson("{service: ''}", YourParsedData.class);
I typed all this up so if I missed some syntax my apologies.
Your json is invalid and any Json parser wouldn't be able to parse a syntactically incorrect json:
"service": {
"description": null,
"name": "Base",
"id": "4c7a90410529"
}
should be encapsulated in curly braces as mentioned here:
{
"service": {
"description": null,
"name": "Base",
"id": "4c7a90410529"
}
}
A json structure is enclosed within {}. Your response seems to be missing that. You can manually append { and } at the beginning and end of the string to make it into a valid json structure.
Once this is done, you can use Gson to parse your json response normally.
What is the best practice to parse such response?
Use a good enough Json parser. That's more than enough. And try to have a class representing the exact same Structure as the response to avoid parsing the json responses level by level, manually.