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();
}
Related
This question already has answers here:
How to parse JSON in Java
(36 answers)
Closed 5 years ago.
I have a Java String that contains a json object and I do not know how to get this json object from it?
My string is like this:
String myString = "[1,\"{\\\"Status\\\":0,\\\"InstanceNumber\\\":9}\"]";
How can i get the json object from this String?
I would recommend simple plain org.json library. Pass the string in JSONArray and then get the JSONObject. For example something like below :
String myString = "[1,\"{\\\"Status\\\":0,\\\"InstanceNumber\\\":9}\"]";
JSONArray js = new JSONArray(myString);
System.out.println(js);
JSONObject obj = new JSONObject(js.getString(1));
System.out.println(obj);
Output :
[1,"{\"Status\":0,\"InstanceNumber\":9}"]
{"Status":0,"InstanceNumber":9}
Downloadable jar: http://mvnrepository.com/artifact/org.json/json
For sure that you need to use a library lie Jackson or Gson.
I work mostly with gson when I don't have complicated stuff.
So here the output of what you are asking for. I suppose that you don't have the type that you want to convert to (for that I am taking Object).
Here is the code:
import com.google.gson.Gson;
public class Json {
public static void main(String[] args) {
Gson g = new Gson();
String myString = "[1,\"{\\\"Status\\\":0,\\\"InstanceNumber\\\":9}\"]";
Object p = g.fromJson(myString, Object.class);
System.out.println(p.toString());
}
}
And here is the output :
run:
[1.0, {"Status":0,"InstanceNumber":9}]
BUILD SUCCESSFUL (total time: 0 seconds)
You may wanting to manipulate the output object as you wish (I just printed it out).
NOTE: Don't forget to add gson jar to you classpath.
You can use any Json mapping framework to deserialise the String into Java object. Below example shows how to do it with Jackson:
String myString = "[1,\"{\\\"Status\\\":0,\\\"InstanceNumber\\\":9}\"]";
ObjectMapper mapper = new ObjectMapper();
List<Object> value = mapper.readValue(myString, new TypeReference<List<Object>>() {});
Map<String, Object> map = mapper.readValue(value.get(1).toString(), new TypeReference<Map<String, Object>>() {});
System.out.println(map);
Here's the documentation.
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.(CycleDetect‌​ionStrategy.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 have one Model Object. In which, i have multiple values. I want to store this Values in SQLite. But data is large, so i want to store Direct Model object
in databse. So i convert model Object to string and store it into database.
Now, Problem is that how to convert this String value to Model Object.
If you have any idea, please share that with Me.
For example,
Person p = new Person();
p.setname("xyz");
p.setage("18");`
String person=p.toString();
Now How to get this "person" string back to Person "p" model object.
This is my code.
ContentValues values = new ContentValues();
String favorite_id = UUID.randomUUID().toString();
values.put(EMuseumLocalData.KEY_FAVORITE_EXHIBITS_ID, favorite_id);
values.put(EMuseumLocalData.KEY_EXHIBIT_SUBCATEGORY_ITEM_ID, Integer.parseInt(categoryByCustomerList.get(position).getSubCategoryItemID()));
try {
Gson gson = new Gson();
String personString = gson.toJson(getAllCategory.get(position).toString());
values.put(EMuseumLocalData.KEY_EXHIBIT_SUBCATEGORY_ITEM_DATA, personString);
Gson gson1 = new Gson();
CategoryByCustomer categoryByCustomer = gson1.fromJson(personString, categoryByCustomer.getName());
} catch (JSONException e) {
e.printStackTrace();
}
You should use GSON or similar libs for this.
Store to DB
For example If you use GSON
Person p = new Person();
p.setname("xyz");
p.setage("18");
Gson gson = new Gson();
String personString = gson.toJson(p);
Now store this personString to DB.
Read from DB
Get back this object from database, read string from DB and convert it to object like below
String personStringFromDB = READ_LOGIC_OF_DB;
Gson gson = new Gson();
Person p = gson.fromJson(personStringFromDB, Person.class);
For more information, read GSON - Gson Example
Consider using a json string representation of the Model Object. There are many java libraries like Jackson, Gson etc., available to help you with serialization/deserialization part.
Here's a sample code to do this in Jackson
//For conversion of Person object(person) to json String:
String personJsonString = new com.fasterxml.jackson.databind.ObjectMapper().writeValueAsString(person);
//For conversion of json String back to Person object(person)
Person person = new com.fasterxml.jackson.databind.ObjectMapper().readValue(personJsonString, Person.class);
You can make Model Object serializable. You need to store the serialized object in SQLite. When you need it, you just get that serialized object from SOLite and deserialize it.
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.
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);