I came across the issue when I have the following JSONObject (org.json):
{
"float1": 0.0,
"float2": 0.1
}
When I call toString method on the object I get the string:
{"float1": 0,"float2": 0.1}
so 0.0 is converted to 0, which causes many problems for me. Does anybody know how to fix that?
I think this is what you wants. However this solution will force you to use your own class extended from JSONObject and it's only functionality is to override the toString() method of JSONObject, i don't know if it's worth it.
import org.json.JSONObject;
import org.json.JSONException;
public class Test extends JSONObject {
public Test(String in) throws JSONException {
super(in);
}
public static Test jsonObj = null;
public static void main(String[] args) throws JSONException {
jsonObj = new Test("{float1: 0.0, float2: 0.1}");
System.out.println(jsonObj.toString());
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("{");
String[] box = JSONObject.getNames(jsonObj);
for (int i = 0; i < JSONObject.getNames(jsonObj).length; i++) {
try {
sb.append(box[i])
.append(" ")
.append(String.format(Locale.ENGLISH, "%.1f",
jsonObj.get(box[i])))
.append(i != JSONObject.getNames(jsonObj).length - 1 ? ","
: "");
} catch (JSONException e) {
e.printStackTrace();
}
}
sb.append("}");
return sb.toString();
}
}
I will try Gson to implement this.
Gson gson = new GsonBuilder().registerTypeAdapter(Double.class, new DoubleSerializer()).create();
TestBean bean = gson.fromJson(jsonInput, TestBean.class);
String jsonOutput = gson.toJson(bean);
DoubleSerializer:
class DoubleSerializer implements JsonSerializer<Double> {
public JsonElement serialize(Double src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(String.format("%.1f", src));
}
}
TestBean.java:
public class TestBean {
private Double float1;
private Double float2;
public Double getFloat1() {
return float1;
}
public void setFloat1(Double float1) {
this.float1 = float1;
}
public Double getFloat2() {
return float2;
}
public void setFloat2(Double float2) {
this.float2 = float2;
}
}
If jsonInput is
{
"float1": 0.0,
"float2": 1.31
}
The jsonOutput will be:
{
"float1": "0.0",
"float2": "1.3"
}
Related
I need to parse the XML string into Object. Please find the class and XML string details below
Country class
public class Country {
private String Country_Name;
private String Country_Capital;
private String Country_Foundation_Date;
private String Country_Continent;
private String Country_Population;
public String getCountry_Name() {
return Country_Name;
}
public void setCountry_Name(String country_Name) {
Country_Name = country_Name;
}
public String getCountry_Capital() {
return Country_Capital;
}
public void setCountry_Capital(String country_Capital) {
Country_Capital = country_Capital;
}
public String getCountry_Foundation_Date() {
return Country_Foundation_Date;
}
public void setCountry_Foundation_Date(String country_Foundation_Date) {
Country_Foundation_Date = country_Foundation_Date;
}
public String getCountry_Continent() {
return Country_Continent;
}
public void setCountry_Continent(String country_Continent) {
Country_Continent = country_Continent;
}
public String getCountry_Population() {
return Country_Population;
}
public void setCountry_Population(String country_Population) {
Country_Population = country_Population;
}
}
Parse Code Implementation
import java.io.StringReader;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;
public class ParseXMLStringtoObject {
public static String getXMLString() {
StringBuilder returnString = new StringBuilder();
returnString.append("<output xmlprop = \"somevalue\"> ");
returnString.append("<Country> ");
returnString.append("<Country_Name equals=\"Spain\" type=\"1\" /> ");
returnString.append("<Country_Capital equals = \"Madrid\" type=\"1\" /> ");
returnString.append("<Country_Foundation_Date equals=\"1469-10-19\" type=\"3\" /> ");
returnString.append("<Country_Continent equals=\"Europe\" type = \"1\" /> ");
returnString.append("<Country_Population equals=\"45\" type = \"2\" /> ");
returnString.append("</Country> ");
return returnString.toString();
}
public static Object getObjectFromStringXml(Class<Country> country)
throws IllegalAccessException, InstantiationException {
Object obj = getObject(country.newInstance());
try {
StringReader reader = new StringReader(getXMLString());
JAXBContext context = JAXBContext.newInstance(country);
Unmarshaller jaxbUnmarshaller = context.createUnmarshaller();
JAXBElement<?> root = jaxbUnmarshaller.unmarshal(new StreamSource(reader), country);
obj = root.getValue();
} catch (Exception e) {
System.out.printf("Exception occoured while unmarshalling xml String to " + obj.getClass() +" Object", e);
}
return obj;
}
private static Object getObject(Object obj) {
if (obj instanceof Country) {
obj = (Country) obj;
}
return obj;
}
public static void main(String[] args) {
Country country = new Country();
//Class<Country> countryObj = new Class<Country>(); // I don't know how to convert my Country object
//or don't know the input value to the getObjectFromStringXml method
ParseXMLStringtoObject parseXML = new ParseXMLStringtoObject();
try{
//This is the place I have the doubt to call the parse method, regarding input
Object obj = parseXML.getObjectFromStringXml(Class<Country> countryObj);
}
catch(Exception e) {
e.printStackTrace();
}
}
}
Where type attribute indicates the type of the values present in equals attribute. For example 1 indicates String, 2 indicates int and 3 indicates list.
Can anyone let me know the solution to map the above xml string into Java Object.
You can try unmarshalling to java object using JAXB something like below:
public static Object getObjectFromStringXml(String xml, Class<Country> country)
throws IllegalAccessException, InstantiationException {
Object obj = getObject(country.newInstance());
try {
StringReader reader = new StringReader(xml);
JAXBContext context = JAXBContext.newInstance(country);
Unmarshaller jaxbUnmarshaller = context.createUnmarshaller();
JAXBElement<?> root = jaxbUnmarshaller.unmarshal(new StreamSource(
reader), country);
obj = root.getValue();
} catch (Exception e) {
log.info("Exception occoured while unmarshalling xml String to " + obj.getClass() +" Object", e);
}
return obj;
}
private static Object getObject(Object obj) {
if (obj instanceof Country) {
obj = (Country) obj;
}
return obj;
}
I'm trying to get the JSON values from Distance24 JSON output via Google GSON.
But I can't figure out what and where the Exception comes from (I'm using Google AppEngine with Java).
Here's the class from which i send and get the request and response.
package de.tum.in.eist.distance;
import java.io.IOException;
import javax.inject.Inject;
import java.net.URL;
import com.google.appengine.api.urlfetch.HTTPResponse;
import com.google.appengine.api.urlfetch.URLFetchService;
import com.google.gson.JsonObject;
import de.tum.in.eist.JsonHelper;
import de.tum.in.eist.URLFetchServiceHelper;
public class Distance24Client {
private final URLFetchService service;
#Inject
public Distance24Client(URLFetchService service) {
this.service = service;
}
public Distance24 getDistanceAPI(String source, String destination) throws IOException {
URL url = new URL("http://www.distance24.org/route.json?stops=" + source + "|" + destination);
HTTPResponse response = service.fetch(url);
String jsonString = URLFetchServiceHelper.toString(response);
try {
JsonObject json = JsonHelper.parse(jsonString);
return toDistance24(json);
} catch (Exception e) {
throw new IOException("Error ocurred in getDistanceAPI(): " + e.getMessage());
}
}
private Distance24 toDistance24(JsonObject response) {
if (!(response.get("stops").getAsJsonObject().getAsJsonArray().size() != 0)) {
throw new IllegalArgumentException("No Status set from Distance24 API");
} else {
JsonObject distances = response.get("distances").getAsJsonObject();
return new Distance24(distances);
}
}
}
And here's the Distance24 Object:
package de.tum.in.eist.distance;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
public class Distance24 {
private int[] distances;
private int totalDistance;
private Double sourceLat;
private Double sourceLon;
private Double destLat;
private Double destLong;
public Distance24(JsonObject distances) {
this.setDistances(getIntArray(distances));
this.setTotalDistance(getSum(this.distances));
this.setSourceLat(distances.get("stops").getAsJsonObject().getAsJsonArray().get(0).getAsJsonObject().get("latitude").getAsDouble());
this.setSourceLon(distances.get("stops").getAsJsonObject().getAsJsonArray().get(0).getAsJsonObject().get("longitude").getAsDouble());
this.setDestLat(distances.get("stops").getAsJsonObject().getAsJsonArray().get(1).getAsJsonObject().get("latitude").getAsDouble());
this.setDestLong(distances.get("stops").getAsJsonObject().getAsJsonArray().get(1).getAsJsonObject().get("longitude").getAsDouble());
}
private int[] getIntArray(JsonObject array) {
JsonArray distances = array.getAsJsonArray();
int[] result = new int[distances.size()];
for(int i = 0; i < distances.size(); i++) {
result[i] = distances.get(i).getAsInt();
}
return result;
}
private int getSum(int[] array) {
int sum = 0;
for(int element : array) {
sum += element;
}
return sum;
}
private void setDistances(int[] distances) {
this.distances = distances;
}
public int getTotalDistance() {
return totalDistance;
}
public void setTotalDistance(int totalDistance) {
this.totalDistance = totalDistance;
}
public Double getSourceLat() {
return sourceLat;
}
public void setSourceLat(Double sourceLat) {
this.sourceLat = sourceLat;
}
public Double getSourceLon() {
return sourceLon;
}
public void setSourceLon(Double sourceLon) {
this.sourceLon = sourceLon;
}
public Double getDestLat() {
return destLat;
}
public void setDestLat(Double destLat) {
this.destLat = destLat;
}
public Double getDestLong() {
return destLong;
}
public void setDestLong(Double destLong) {
this.destLong = destLong;
}
}
As a result, I get the whole JSON Object as a String output for e.getMessage(). So I guess the information retrieving works, even though it's on the wrong part of the code.
Plus in the same try-catch-block of the code (Distance24Client, method "toDistance24") it says, the error ocurred in line 30, which is the return statement of the "toDistance24" method.
(clickable)
Running http://www.distance24.org/route.json?stops=detroit|dublin from my browser gives me
{"stops":[{"region":"Michigan ...
"distances":[5581]}
So distances is an array and not an object.
So your line:
JsonObject distances = response.get("distances").getAsJsonObject();
is wrong. Read distances as a JsonArray.
Create a method to handle array or no-array
public static JsonElement toJsonElement(String jsonString) {
JsonParser parser = new JsonParser();
JsonElement jsonElement = parser.parse(jsonString);
JsonElement result = null;
if (jsonElement instanceof JsonObject) {
result = jsonElement.getAsJsonObject();
} else if (jsonElement instanceof JsonArray) {
result = jsonElement.getAsJsonArray();
} else {
throw new IllegalArgumentException(jsonString + " is not valid JSON stirng");
}
return result;
}
I am building an android application and I am new to json. I am fetching below josn formate -
{
"contact"[
{
"key1": "hey1",
"key2": [
{
"key3": "hey2"
}
]
}
]
}
I am using below code to fetch key1 value. Now problem I am facing is how to fetch key3 value -
jsonString = http.makeServiceCall(url, ServiceHandler.GET, null);
if (jsonString != null) {
try {
JSONObject jsonObj = new JSONObject(jsonString);
// Getting JSON Array node
questions = jsonObj.getJSONArray(TAG_CONTACTS);
for (int i = 0; i < questions.length(); i++) {
temp_obj = questions.getJSONObject(i);
key1Array.add(temp_obj.getString("key1").toString());
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Please help me
If you want to use Gson to parse your json data. Let try it:
First of all, you must modify your json like this:
{
"contact":[
{
"key1": "hey1",
"key2": [
{
"key3": "hey2"
}
]
}
]
}
Second add Gson to your libs and sync build.gradle: download here extract it, and copy/past gson-2.2.4.gson to libs folder.
Third Create some class:
FullContents.java:
public class FullContents {
private List<ObjectKey> contact;
public List<ObjectKey> getContact() {
return contact;
}
public void setContact(List<ObjectKey> contact) {
this.contact = contact;
}
}
ObjectKey.java:
public class ObjectKey {
private String key1;
private List<ObjectKey3> key2;
public List<ObjectKey3> getKey2() {
return key2;
}
public void setKey2(List<ObjectKey3> key2) {
this.key2 = key2;
}
public String getKey1(){
return key1;
}
public void setKey1(String key1){
this.key1 = key1;
}
}
ObjectKey3.java:
public class ObjectKey3 {
private String key3;
public String getKey3(){
return key3;
}
public void setKey3(String key3){
this.key3 = key3;
}
}
And Finally, get data from url:
private class ParseByGson extends AsyncTask<String,Void,FullContents> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected FullContents doInBackground(String... params) {
FullContents fullContents = null;
try {
URL url=new URL(params[0]);
InputStreamReader reader=new InputStreamReader(url.openStream(),"UTF-8");
fullContents=new Gson().fromJson(reader,FullContents.class);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return fullContents;
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(FullContents results) {
super.onPostExecute(results);
ObjectKey objectKey = results.getContact().get(0);
Log.e(">>",objectKey.getKey1()+"--");
}
}
you can put below code to onCreate:
ParseByGson parseByGson = new ParseByGson();
parseByGson.execute(urlStringHere);
Update: Explain
1st of all: your json appears to be not valid (missing ':' after "content");
After reviewing thins:
You can use the named getters to retrieve many types of results (object, int, string, etc);
JSONObject contact = jsonObj.getJSONObject("contact"); // {"key1":"hey1","key2":[{"key3":"hey2"}]}
or
String key1 = jsonObj.getString("key1"); // hey1
To retrieve key3, you should use:
JSONObject contact = jsonObj.getJSONObject("contact");
JSONObject key2 = contact.getJSONObject("key2");
String key3 = key2.getString("key3");
Adapt the following code to what you are coding
for (int i = 0; i < questions.length(); i++) {
temp_obj = questions.getJSONObject(i);
key1Array.add(temp_obj.getString("key1"));
JSONObject temp_objKey2 = temp_obj.getJSONObject("key2");
Key2Object key2Object = new Key2Object();
key2Object.add(temp_objKey2.getString("key3"));
key1Array.add(key2Object);
}
I want to deserialize a JSON response but I'm not sure about the format. The format can vary in each case. For example the response contains a field named "error" which may be false (boolean) or an object that describes the error eg. "error": { "code": xxx , "description":"etc"}
How should I implement a class that covers both cases? Is there any way to do this?
Thanks
I would prefer using a TypeAdapter for your case:
private static class Error {
private boolean hasError;
private int code;
private String description;
}
private static class ErrorTypeAdapter extends TypeAdapter<Error> {
#Override
public Error read(JsonReader jsonReader) throws IOException {
Error response = null;
jsonReader.beginObject();
while (jsonReader.hasNext()) {
String currentJsonName = jsonReader.nextName();
if("error".equals(currentJsonName)) {
response = new Error();
try {
response.hasError = jsonReader.nextBoolean();
} catch (Exception e) {
response.hasError = true;
jsonReader.beginObject();
}
} else if("code".equals(currentJsonName)) {
response.code = jsonReader.nextInt();
} else if ("description".equals(currentJsonName)) {
response.description = jsonReader.nextString();
}
}
if(response.hasError) {
jsonReader.endObject();
}
jsonReader.endObject();
return response;
}
#Override
public void write(JsonWriter jsonWriter, Error response)
throws IOException {
jsonWriter.beginObject();
jsonWriter.name("hasError").value(response.hasError);
jsonWriter.name("code").value(response.code);
jsonWriter.name("description").value(response.description);
jsonWriter.endObject();
}
}
To test it you can use:
String val1 = "{\"error\": {\"code\": 1 , \"description\":\"etc\"}}";
String val2 = "{\"error\": false}";
final GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Error.class, new ErrorTypeAdapter());
gsonBuilder.setPrettyPrinting();
final Gson gson = gsonBuilder.create();
gson.fromJson(val1, Error.class);
gson.fromJson(val2, Error.class);
You can read more about TypeAdapters here and also some great examples here.
I'm trying to read a very heavy JSON (over than 6000 objects) and store them on a hash map to insert it into my database later.
But the problem is that I face with OOM and that's cause from my heavy JSON, however GSON library should rid me from this situation, but it is not !!!
Any ideas?
public Map<String,String> readJsonStream(InputStream in) throws IOException
{
JsonReader reader = new JsonReader(new InputStreamReader(in, "UTF-8"));
Map<String,String> contentMap = new HashMap<String,String>();
Gson mGson = new Gson();
contentMap = mGson.fromJson(reader, contentMap.getClass());
reader.close();
return contentMap;
}
From my experience, yes you can use google GSON to stream JSON data this is an example how to do it :
APIModel result = new APIModel();
try {
HttpResponse response;
HttpClient myClient = new DefaultHttpClient();
HttpPost myConnection = new HttpPost(APIParam.API_001_PRESENT(
serial_id, api_key));
try {
response = myClient.execute(myConnection);
Reader streamReader = new InputStreamReader(response
.getEntity().getContent());
JsonReader reader = new JsonReader(streamReader);
reader.beginObject();
while (reader.hasNext()) {
String name = reader.nextName();
if (name.equals("result")) {
if (reader.nextString() == "NG") {
result.setResult(Util.API_001_RESULT_NG);
break;
}
} else if (name.equals("items")) {
result = readItemsArray(reader);
} else {
reader.skipValue(); // avoid some unhandle events
}
}
reader.endObject();
reader.close();
} catch (Exception e) {
e.printStackTrace();
result.setResult(Util.API_001_RESULT_NG);
}
} catch (Exception e) {
e.printStackTrace();
result.setResult(Util.API_001_RESULT_NG);
}
readItemsArray function :
// read items array
private APIModel readItemsArray(JsonReader reader) throws IOException {
APIModel result = new APIModel();
String item_name, file_name, data;
result.setResult(Util.API_001_RESULT_OK);
reader.beginArray();
while (reader.hasNext()) {
item_name = "";
file_name = "";
data = "";
reader.beginObject();
while (reader.hasNext()) {
String name = reader.nextName();
if (name.equals("name")) {
item_name = reader.nextString();
} else if (name.equals("file")) {
file_name = reader.nextString();
} else if (name.equals("data")) {
data = reader.nextString();
} else {
reader.skipValue();
}
}
reader.endObject();
result.populateModel("null", item_name, file_name, data);
}
reader.endArray();
return result;
}
API Model Class :
public class APIModel {
private int result;
private String error_title;
private String error_message;
private ArrayList<String> type;
private ArrayList<String> item_name;
private ArrayList<String> file_name;
private ArrayList<String> data;
public APIModel() {
result = -1;
error_title = "";
error_message = "";
setType(new ArrayList<String>());
setItem_name(new ArrayList<String>());
setFile_name(new ArrayList<String>());
setData(new ArrayList<String>());
}
public void populateModel(String type, String item_name, String file_name, String data) {
this.type.add(type);
this.item_name.add(item_name);
this.file_name.add(file_name);
this.data.add(data);
}
public int getResult() {
return result;
}
public void setResult(int result) {
this.result = result;
}
public String getError_title() {
return error_title;
}
public void setError_title(String error_title) {
this.error_title = error_title;
}
public String getError_message() {
return error_message;
}
public void setError_message(String error_message) {
this.error_message = error_message;
}
public ArrayList<String> getType() {
return type;
}
public void setType(ArrayList<String> type) {
this.type = type;
}
public ArrayList<String> getItem_name() {
return item_name;
}
public void setItem_name(ArrayList<String> item_name) {
this.item_name = item_name;
}
public ArrayList<String> getFile_name() {
return file_name;
}
public void setFile_name(ArrayList<String> file_name) {
this.file_name = file_name;
}
public ArrayList<String> getData() {
return data;
}
public void setData(ArrayList<String> data) {
this.data = data;
}
}
before I use the streaming API from google GSON I also got OOM error because the JSON data I got is very big data (many images and sounds in Base64 encoding) but with GSON streaming I can overcome that error because it reads the data per token not all at once. And for Jackson JSON library I think it also have streaming API and how to use it almost same with my implementation with google GSON. I hope my answer can help you and if you have another question about my answer feel free to ask in the comment :)