Identify JsonObject vs JsonArray using Gson - java

I have the following validator which checks if a JSON string is valid using Gson. It works well with a JSON object but it blows up when you pass it a JSON array.
JsonStringValidator
public class JsonStringValidator implements ConstraintValidator<JsonString, String> {
private static final TypeAdapter<JsonObject> strictGsonObjectAdapter =
new Gson().getAdapter(JsonObject.class);
#Override
public boolean isValid(String jsonString, ConstraintValidatorContext context) {
try {
try (JsonReader reader = new JsonReader(new StringReader(jsonString))) {
strictGsonObjectAdapter.read(reader);
reader.hasNext();
return true;
}
} catch (IOException e) {
return false;
}
}
}
Works
{
"books":[
{
"isbn": "12345"
}
]
}
Fails
[
{
"isbn": "12345"
}
]
Exception
com.google.gson.JsonSyntaxException: Expected a com.google.gson.JsonObject but was com.google.gson.JsonArray
So it seems like I also need a strictGsonArrayAdapter.
But how can I determine if it's an array or object before calling strictGsonObjectAdapter?

I was able to determine whether the JSON string was an array or an object by using JsonParser to give me a JsonElement.
The JsonElement class has boolean methods for isJsonArray() and isJsonObject().
JsonElement jsonElement = JsonParser.parseString(jsonString);
log.info(jsonElement.isJsonArray());
log.info(jsonElement.isJsonObject());

Related

How to use gson for getstring of json?

I am new to use gson.
I found a lots of tutorial there I can learn of gson but there are using recylerview and model file.
JsonObjectRequest request = new JsonObjectRequest(LoginUrl, new JSONObject(params),
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d(TAG , String.valueOf(response));
try {
String statusObject = response.getString("status");
String msgObject = response.getString("msg");
if (statusObject.equals("200")) {
JSONArray jsonArray = response.getJSONArray("response");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject managerResponse= jsonArray.getJSONObject(i);
// userIdObject = managerResponse.getString("user_id");
// String nameObject = managerResponse.getString("name");
// String emailObject = managerResponse.getString("email");
// String mobileObject = managerResponse.getString("mobile");
// String postobject = managerResponse.getString("post");
// pojectObject = managerResponse.getString("project");
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
}
Here I can get data from jsonrequest using volley but unable to do that same process using volley and gson. Is there any way to use gson?
Thank You.
Update
My JSON Response
{
"status": "200",
"msg": "Successfully",
"response": [
{
"user_id": "1",
"name": "HEMANT OJHA",
"email": "hemguna#gmail.com",
"mobile": "9584919991",
"address1": "C92, PALLAWI NAGAR BABADIYA KALAN",
"user": "admin",
"api_token": "admin"
}
]
}
Generating POJO class from JSON
// Considering your response consists of json objects & json array
// Create a POJO class for your response with the link above
{
"keyOne": 1,
"keyTwo": "Some Value",
"someArray": [{
"key": "Value"
},
{
"key": "Value"
}
]
}
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class ExampleClass {
#SerializedName("keyOne")
#Expose
private int keyOne;
#SerializedName("keyTwo")
#Expose
private String keyTwo;
#SerializedName("someArray")
#Expose
private List<SomeArray> someArray = null;
public int getKeyOne() {
return keyOne;
}
public void setKeyOne(int keyOne) {
this.keyOne = keyOne;
}
public String getKeyTwo() {
return keyTwo;
}
public void setKeyTwo(String keyTwo) {
this.keyTwo = keyTwo;
}
public List<SomeArray> getSomeArray() {
return someArray;
}
public void setSomeArray(List<SomeArray> someArray) {
this.someArray = someArray;
}
}
// Parsing JSON response with GSON
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
ExampleClass resultObj = gson.fromJson(jsonObject.toString(), ExampleClass.class);
int keyOneValue = resultObj.getKeyOne() // First JSON Object
// Getting String value
String keyTwoValue = resultObj.getKeyTwo() // Second JSON Object
List<SomeArray> yourJSONArray = resultObj.getSomeArray() // Getting JSON Array contents
// Depending on JSON response that you've updated in your question
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
ExampleClass resultObj = gson.fromJson(jsonObject.toString(),ExampleClass.class);
String status = resultObj.getStatus();
String msg = resultObj.getMsg();
List<Response> responseList = resultObj.getResponse();
The best way to use for entire app is create a Utils class and use it for conversion.
GsonUtils.java
// This Class is useful for mapping Json into Java Objects and vice versa.
public class GsonUtils {
private static final Gson gson = new Gson();
// This will Convert Java Objects into JSON String...
public static String toGson(Object object) {
return gson.toJson(object);
}
// Gives Java Objects from JSON
public static <T> T fromGson(String json, Class<T> type) {
return gson.fromJson(json, type);
}
public static JsonArray fromGson(String json) {
return new JsonParser().parse(json).getAsJsonArray();
}
}
Now convert any json to and from POJO via,
POJO pojoObj = GsonUtils.toGson(POJO.class);
Try this
JSON response
String str = new Gson().toJson(response)

GSON deserialize/serialize hierarchy class

I have a java app that send json content to my server (c++). I my server i receive the json, do the parse, the validation, etc and send back the response with json too.
I have one request in my java app that have this json body (example):
{
"a": "a",
"b": "b",
"searchMethod": {
"searchByUser": {
"userId": "userId"
}
}
}
But for the same command i can have other searchMethod:
{
"a": "a",
"b": "b",
"searchMethod": {
"searchByEmail": {
"email": "user#user.com"
}
}
}
So, when the user do the request we can send to my server one of this two different json bodys. I never know what searchMethod we send. This part (check what searchMethod the user send, etc), i do in my c++ server when i receive the json. So in my java app i only need to use the gson to send a searchMethod object with their content.
This my class to do the request:
public class RequestExample implements SerializableJSON
{
public String a;
public String b;
public RequestExample(String a, b)
{
this.a = a;
this.b = b;
}
public static RequestExample fromStringJson(String data)
{
try
{
Gson gson = new Gson();
return gson.fromJson(data, RequestExample.class);
}
catch(Exception e)
{
return null;
}
}
public static RequestExample fromBytesJson(byte[] data)
{
if (data == null) return null;
try
{
String str = new String(data, "utf-8");
return fromStringJson(str);
}
catch (Exception e)
{
return null;
}
}
#Override
public String toJsonString()
{
try
{
Gson gson = new Gson();
return gson.toJson(this);
}
catch(Exception e)
{
return null;
}
}
#Override
public byte[] toJsonBytes()
{
try
{
return this.toJsonString().getBytes("utf-8");
}
catch (Exception e)
{
return null;
}
}
}
I already implement the fields a and b because its always the same in this request. In this class the fromStringJson(String data) receive the data string field that contain all json that the user try to send. In this function i use the gson.fromJson to convert this string to a json object type of my RequestExample class.
So the main question is: How to adapt my RequestExample class to convert the string to a json object regardless of the type of searchMethod. Like i said in my java app i dont need to know how seachMethod the user choose. In my server yes, but this part i already implement. So for now, i only need to send the request to my server.
If you don't use field searchMethod, you can implement it like a Map
private Map<String, Object> searchMethod = new HashMap<>();
or
private Map<String, Map<String,Object>> searchMethod = new HashMap<>();
or
private Map<String, Map<String,String>> searchMethod = new HashMap<>();

Android/java Parsing JSON with numbered data [duplicate]

This question already has answers here:
How to parse a dynamic JSON key in a Nested JSON result?
(5 answers)
Closed 7 years ago.
I have been looking for parsing JSON data in java/android. unfortunately, there is no JSON that same as mine. i have JSON data that include weird number, looks like :
{
"formules": [{"1":
{
"formule": "Linear Motion",
"url": "qp1"
},"2":
{
"formule": "Constant Acceleration Motion",
"url": "qp2"
},"3":
{
"formule": "Projectile Motion",
"url": "qp3"
}
}
]
}
Please help me how to parse this in Java/android. Thanks
try this
JSONObject jsonObject = new JSONObject(string);
JSONArray jsonArray = jsonObject.getJSONArray("formules");
JSONObject jsonObject1 = jsonArray.getJSONObject(0);
Now you can access object "1" as
JSONObject json = jsonObject1.getJSONObject("1");
or use iterator to iterate as below
Iterator keys = jsonObject1.keys();
while(keys.hasNext()) {
// loop to get the dynamic key
String currentDynamicKey = (String)keys.next();
JSONObject json = jsonObject1.getJSONObject(currentDynamicKey);
}
let me know if it works
For parsing Json in Android, I have found the Gson Library to be helpful
http://mvnrepository.com/artifact/com.google.code.gson/gson/2.3
What it would require is creating a pojo class that represents your object. Might look something like
public class ClassPojo
{
private Formules[] formules;
public Formules[] getFormules ()
{
return formules;
}
public void setFormules (Formules[] formules)
{
this.formules = formules;
}
#Override
public String toString()
{
return "ClassPojo [formules = "+formules+"]";
}
}
public class Formules
{
private Formule 3;
private Forumle 2;
private Formule 1;
}
public class Formule
{
private String formule;
private String url;
public String getFormule ()
{
return formule;
}
public void setFormule (String formule)
{
this.formule = formule;
}
public String getUrl ()
{
return url;
}
public void setUrl (String url)
{
this.url = url;
}
#Override
public String toString()
{
return "ClassPojo [formule = "+formule+", url = "+url+"]";
}
}
then to convert it to and from JSon,you could use
//Convert to JSON
ClassPojo pojo = new ClassPojo();
Gson gson = new Gson();
String json = gson.toJson(pojo);
//COnvert back to Java object
ClassPojo pojo = gson.fromJson(json,ClassPojo.class);

Android - Save JSON from InputStream into String

I'm trying to parse this JSON I get from a HttpURLConnection in Android.
{
"responsejson":
{
"value1": [
{
"data": "Call",
"label": "Call",
"default": false
},
{
"data": "Email",
"label": "Email",
"default": false
}
],
"value2": [
{
"attributes": {
"type": "Status",
"url": "/..."
},
"IsOpened": false,
"IsDefault": true,
"TechLabel": "NotStarted",
"Id": "01Jb"
},
{
"attributes": {
"type": "Status",
"url": "/..."
},
"IsOpened": false,
"IsDefault": false,
"TechLabel": "InProgress",
"Id": "01Jb"
},
{
"attributes": {
"type": "Status",
"url": "/..."
},
"IsOpened": true,
"IsDefault": false,
"TechLabel": "Completed",
"Id": "01Jb"
}
],
...
}
}
What I want to do is save the content of value1 in a string, the content of value2 in another string,... because I need to store it in the database, so in the future I can load and parse it. I am using JsonReader but it's not possible to do this with JsonReader.
// ...
inputStream = conn.getInputStream();
JsonReader json = new JsonReader(new InputStreamReader(in));
json.beginObject();
while (json.hasNext()) {
String valueName = json.nextName();
// String content = ?????
}
json.endObject();
// ...
Any ideas? Custom objects are not possible due to we never know which values the JSON is going to show.
Use this to convert JSON array to string
private String convertStreamToString(InputStream is) {
/*
* To convert the InputStream to String we use the
* BufferedReader.readLine() method. We iterate until the
* BufferedReader return null which means there's no more data to
* read. Each line will appended to a StringBuilder and returned as
* String.
*/
BufferedReader reader = new BufferedReader(
new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
Use Gson to parse the JSON that you receive in InputStream. Then you can get the ArrayList from that parsed object. Again, use Gson to serialize the arraylist back to JSON.
This code works for your example json.
public class Value1 {
public String data,label;
#SerializedName("default")
public boolean isdefault;
}
public class Value2 {
public Attributes attributes;
public boolean IsOpened,IsDefault;
public String TechLabel,Id;
}
public class Attributes {
public String type,url;
}
String jsonString = "{\"responsejson\":{\"value1\":[{\"data\":\"Call\",\"label\":\"Call\",\"default\":false},{\"data\":\"Email\",\"label\":\"Email\",\"default\":false}],\"value2\":[{\"attributes\":{\"type\":\"Status\",\"url\":\"/...\"},\"IsOpened\":false,\"IsDefault\":true,\"TechLabel\":\"NotStarted\",\"Id\":\"01Jb\"},{\"attributes\":{\"type\":\"Status\",\"url\":\"/...\"},\"IsOpened\":false,\"IsDefault\":false,\"TechLabel\":\"InProgress\",\"Id\":\"01Jb\"},{\"attributes\":{\"type\":\"Status\",\"url\":\"/...\"},\"IsOpened\":true,\"IsDefault\":false,\"TechLabel\":\"Completed\",\"Id\":\"01Jb\"}]}}";
try {
org.json.JSONObject object = new JSONObject(jsonString);
jsonString = object.getString("responsejson");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
JsonParser parser = new JsonParser();
JsonObject obj = parser.parse(jsonString).getAsJsonObject();
List<Value1> list1 = new Gson().fromJson(obj.get("value1"), new TypeToken<List<Value1>>() {}.getType());
List<Value2> list2 = new Gson().fromJson(obj.get("value2"), new TypeToken<List<Value2>>() {}.getType());
Since you do not know json structure beforehand, your best bet is to use GSON 2.0 feature that supports default maps and lists.
Use the following code to deserialize :
Object object = new Gson().fromJson(jsonString, Object.class);
The created object is a Map (com.google.gson.internal.LinkedTreeMap) which looks like this (for the above example)
{responsejson={value1=[{data=Call, label=Call, default=false}, {data=Email, label=Email, default=false}], value2=[{attributes={type=Status, url=/...}, IsOpened=false, IsDefault=true, TechLabel=NotStarted, Id=01Jb}, {attributes={type=Status, url=/...}, IsOpened=false, IsDefault=false, TechLabel=InProgress, Id=01Jb}, {attributes={type=Status, url=/...}, IsOpened=true, IsDefault=false, TechLabel=Completed, Id=01Jb}]}}
Use the generated object, parse it and save it in your db.
You can serialize that map back to JSON using :
String json = new Gson().toJson(object);
Hope this helps you.
just read the stream regularly and save it into a regular String, then parse that String :
// to get the general object that contains all the values
JSONObject json = new JSONObject(json_readed);
JSONObject response = json.getJSONObject("responsejson");
// to get the values
List<JSONArray> all_values = new ArrayList<JSONArray>();
Iterator<?> keys = response.keys();
while( keys.hasNext() ){
String value = (String)keys.next();
if( response.get(value) instanceof JSONArray ){
all_values.add(response.getJSONArray(value));
}
}
now you have all the values(whatever what's it's name id) combined into that ArrayList called(all_values).
Note that the JSON you provided in your question is missing opening"{" and closing"}" brackets in the beginning and the ending of it.
What you need to do is, first create a JsonObject from the json string representation, at this stage no specifics are given.
JSONObject object = new JSONObject("json_here"); //catch all exceptions thrown.
Interestingly you mentioned that the structure varies, it consider that weird, i am guessing you are pulling from different api instances. What you need to do , create a pojo class mapping the api instance name to the returned json string body.
After you attained the Object of interest, consider using GSON. A Java serialization/deserialization library to convert Java Objects into JSON and back. What you then need to do is to,serialize the pojo class,into an object.Then store into the database. I recommend using realm and not SQLite.
Example serializing the class.
class JClass {
private String jType;
private String json_body;
JClass() {
// no-args constructor
}
}
JClass j = new JClass();
j.jType ="some_type";
j.json_body = "json_body_here";
Gson gson = new Gson();
String json = gson.toJson(j);
then get the json String object, and store in database of choice.
/*
* Method to parse InputStream to String JSON
* */
private String parse(InputStream in){
StringBuilder result;
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
result.append(line);
}
Log.d("JSON Parser", "result: " + result.toString());
return result.toString();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
JSONParser parser = new JSONParser();
List<String> output = new ArrayList<String>();
try {
Object obj = parser.parse(data); // data is JSON
JSONObject jsonObject = (JSONObject) obj;
JSONArray msg = (JSONArray) jsonObject.get("value1");
JSONArray msg2 = (JSONArray) jsonObject.get("value2");
Iterator<String> iterator = msg.iterator();
while (iterator.hasNext()) {
output.add(iterator.next());
}
String[] stringArray = output.toArray(new String[0]);
return stringArray;
} catch (Exception e) {
return null;
}

gson list object attributes are null

I am trying get a list object from json file usiong gson. It returning list with objects but all attributes are null. How to get the objects properly?
json file:
[{"PeriodEndP":"2014-04-06T00:00:00","SiteKeyP":"00035"},{"PeriodEndP":"2014-04-06T00:00:00","SiteKeyP":"00035"}]
ScheduleDTO.java
public class ScheduleDTO {
String periodEndP;
String siteKeyP;
}
GsonEx.java
public class GsonEx {
public static void main(String[] args) {
try
{
JsonReader jsonReader = new JsonReader(new FileReader("F:/schedule.txt"));
Gson gson = new Gson();
Type ScheduleMsgDestType = new TypeToken<List<ScheduleDTO>>(){}.getType();
List<ScheduleDTO> ScheduleList = gson.fromJson(jsonReader, ScheduleMsgDestType);
for(ScheduleDTO t :ScheduleList )
{
System.out.println(t.periodEndP);
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
Make PeriodEndP to periodEndP
and same for SiteKeyP which will be siteKeyP
The names should be the same in the json and code.

Categories