i am getting response in Json array and json object in same key.Json Array is working fine but while parsing json Object i am getting an error
Caused by: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was
BEGIN_OBJECT at line 1 column 204 path $.RenewalPlans.RenewalPlan
Json Object
{"Code":"000","Message":"Success","UserName":"abc","CustomerName":"abc And
Company","PaymentMessage":"You have 55 days left, you can make ADVANCE
payment","RenewalPlans":{"RenewalPlan":{"PlanId":"11111","PlanName":"plan
name","PlanAmount":"1000"}}}
Json Array
{"Code":"000","CustomerName":"abc","Message":"Success","PaymentMessage":"You have 2 days left, you can make ADVANCE payment","RenewalPlans":{"RenewalPlan":[{"PlanAmount":"100","PlanId":"1","PlanName":"Value Standard 25mbps/12mths 1TV (Renew) "},{"PlanAmount":"200","PlanId":"2","PlanName":"30Mbps/12mths SPECIAL OFFER 2077 (1TV) "},{"PlanAmount":"300","PlanId":"3","PlanName":"40Mbps/12mths SPECIAL OFFER 2077 (2TV) (Rs.19775)"},{"PlanAmount":"400","PlanId":"4","PlanName":"60Mbps/12mths SPECIAL OFFER 2077 (3TV) "}]},"Username":"abcd"}
`
String data;
Object json = null;
CustomerdetailsResponse customerDetailsResponse = new Gson().fromJson(new Gson().toJson(response), CustomerdetailsResponse.class);
data = new Gson().toJson(customerDetailsResponse.getRenewalPlans().getRenewalPlan());
try {
json = new JSONTokener(data).nextValue();
if (json instanceof JSONObject) {
CustomerDetailsResponseRenewalPlansRenewalPlan plans = new Gson().fromJson(new Gson().toJson(data), CustomerDetailsResponseRenewalPlansRenewalPlan.class);
renewalPlans.add(plans);
}
//you have an object
else if (json instanceof JSONArray) {
renewalPlans = new Gson().fromJson(data, new TypeToken<ArrayList<RenewalPlans>>() {
}.getType());
}
} catch (JSONException e) {
e.printStackTrace();
}
factory register with Gson
public Gson gson()
{
return Converters.registerAll(new GsonBuilder())
.registerTypeAdapterFactory(AppTypeAdapterFactory.create())
.setLenient()
.create();
}
GsonType Adapter factory
#GsonTypeAdapterFactory
public abstract class AppTypeAdapterFactory implements TypeAdapterFactory {
public static TypeAdapterFactory create(){
return new AutoValueGson_AppTypeAdapterFactory();
}
}
Related
I need to show response on Sign Up, below is my JSON Response.
I should show password is too short(minimum is 5 characters) into one string
{ errors: { password: [ "is too short (minimum is 5 characters)" ] } }
And also I need to parse the response from the following JSON data
as Signature has already been taken
{ errors: { signature: [ "has already been taken" ] } }
Please tell me how to parse the particular data from the JSON data.
Thanks in advance!!!!
You can use below method to parse your data.
private String parseJsonData(String jsonResponse) {
try {
JSONObject jsonObject = new JSONObject(jsonResponse);
JSONObject errorJsonObject = jsonObject.getJSONObject("errors");
JSONArray jsonArray = null;
//has method
if (errorJsonObject.has("password")) {
jsonArray = errorJsonObject.optJSONArray("password");
} else if (errorJsonObject.has(" signature")) {
jsonArray = errorJsonObject.optJSONArray("signature");
}
String errorMessage = jsonArray.getString(0);
return errorMessage;
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}
You can replace unwanted symbols like below code:
errorMessage.repalce("[","");
errorMessage.repalce("]","");
errorMessage.repalce("/"","");
You can use Google's Gson library to do that using the following steps:
Add dependency in your build.gradle(Module:app) file.
dependencies {
implementation 'com.google.code.gson:gson:2.8.5'
}
For latest version of gson library, click here
To parse JSON string to an object use the code below:
Gson gson = new Gson();
// I'm fetching my session stored JSON string
// You can fetch as per your requirement
String jsonStr = session.getJsonStr();
MyObject myObject = (MyObject) gson.fromJson(jsonStr, MyObject.class);
And if you need to convert an object to a JSON string, you can use the below code:
// I'm fetching my session stored Object here
// You can fetch as per your requirement
MyObject myObject = session.getMyObject();
String jsonStr = gson.toJson(myObject);
Make sure you design your object appropriate for the JSON string to match the data types. If you are not sure of the data types in the JSON, you can use this site or any parse and view website to view them.
Hope it helps!
Just try this,
try {
String tost = null;
JSONObject object = new JSONObject(json);
JSONObject errorObject = object.getJSONObject("errors");
if (errorObject.has("password")){
tost = "password "+errorObject.getJSONArray("password").get(0).toString();
} else if (errorObject.has("signature")){
tost = "signature "+errorObject.getJSONArray("signature").get(0).toString();
}
Toast.makeText(MainActivity.this, tost, Toast.LENGTH_SHORT).show();
}catch (Exception e){
e.printStackTrace();
}
I have the following problem:
The answers to my API are always like this "style":
{
"type": "dbUserResponse",
"user": {
"apellido": "canadas",
"email": "rj#canada.es",
"nacimiento": "1995-01-01T00:00:00+01:00",
}
}
That is, field "dbXXXXResponse" and model. That is, field "Response" and model. In this case user. Another example for the model Alert:
{
"type": "dbAlertResponse",
"alert": {
"alertId": 0,
"fecha": "2004-10-19T10:23:54+02:00",
}
}
Oki... What I need? Create a type Adapter deserialize or more?
One generic, or I have to make one typedapter for each model.
I have done the following:
public class GenericDeserializer<T> implements JsonDeserializer<T>
{
#Override
public T deserialize(JsonElement je, Type type, JsonDeserializationContext jdc)
throws JsonParseException
{
// Get the "content" element from the parsed JSON
JsonElement content = je.getAsJsonObject().get("type");
if(content.toString().equals("\"dbUserResponse\"")){
content = je.getAsJsonObject().get("user");
JsonObject jsonObject = content.getAsJsonObject();
if(jsonObject.has("nacimiento")){
String date = jsonObject.get("nacimiento").getAsString();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
Date date2 = null;
try {
date2 = sdf.parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
String newstring = new SimpleDateFormat("yyyy-MM-dd").format(date2);
jsonObject.addProperty("nacimiento", newstring);
content = jsonObject.getAsJsonObject();
}
}
}
if(content.toString().equals("\"dbAlertResponse\"")){
// other case..... etc...
}
else{
//content = '{"error":"mierror"}';
}
// Deserialize it. You use a new instance of Gson to avoid infinite recursion
// to this deserializer
return new Gson().fromJson(content, type);
}
}
Thus, I have managed to successfully obtain the sub JSON "user" and fill my User model in Android.
But the "nacimiento" (date) field is not formatted :-(
I have also created a Singleton Retrofit, I'm not sure if it is correct:
public class SingletonRetrofit {
public static final String BASE_URL = "xxxxxxxxxxxxxxxxxxx";
private static Retrofit retrofit = null;
public static Retrofit getClient() {
Gson gson = new GsonBuilder()
.registerTypeAdapter(User.class, new GenericDeserializer<User>())
.create();
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
}
return retrofit;
}
}
My questions:
1º- How correctly format the date when the model is inside another Json Json like me?
2º- Will I have to create a typeadapter for each model? : -S
Thank you
Why don't you use POJO? Date in JSON is String so you must convert String to Date.
I want to parse JSON with any key on Android.
JSON data consists of any key, array or values.
Here are JSON data and my working code.
I want to put JSON data into a class by using JSON parsing.
JSON data :
{
"d520c8c17c8e":
{ "id":"25689123",
"number":"0e31b1994"
},
"d183c6e9913d":
{
"id":"25689123",
"number":"0e31b1994"
},
"content":"8090986565488990",
"text":"hello",
"status":"ok"
}
My code :
public static MyInfo getMyInfo(JSONObject json) {
MyInfo info = new MyInfo();
if (json == null)
return null;
try {
info.setContent(json.getString("content"));
info.setText(json.getString("text"));
info.setStatus(json.getString("status"));
ArrayList<MyList> mylists = new ArrayList<MyList>();
JSONArray panels = json.getJSONArray(????????????);
for(int i=0;i < panels.length();i++){
JSONObject e2 = panels.getJSONObject(i);
MyList info_list = new MyList();
info_list.setId(e2.getString("id"));
info_list.setNumber(e2.getString("number"));
info_list.add(info_answer);
}
info.setList(info_list);
} catch (JSONException e) {
}
return info;
}
please help me.
Yes this is possible.
Put the JSON you receive in a JSONObject. You can loop trough the keys and get the values out of it.
Example:
//Create json object from string
JSONObject newJson = new JSONObject(json);
// Get keys from json
Iterator<String> panelKeys = newJson.keys();
while(panelKeys.hasNext()) {
JSONObject panel = newJson.getJSONObject(panelKeys.next()); // get key from list
String id = panel.getString("id");
String number = panel.getString("number");
}
I hope this is what you were looking for
I'm working with a REST API that returns a JSON document that starts as follows and includes a "collection" of items with string IDs like "ABC". Note the "routes" field, which contains a series of fields called "ABC", "ABD", "ABE" etc, however routes is not represented as an array in the json, so all these
{
"status":true,
"page":1,
"per_page":500,
"total_count":1234,
"total_pages":8,
"total_on_page":500,
"routes":{
"ABC":[
{
"value":22313,
<......>
I'm using Retrofit and the problem is the routes field is not an array (despite the fact conceptually it certainly is) and Retrofit/Gson require me to create a model object for routes with field vars abc, abd, etc - this is not practical as the data changes. For various reasons changing the server API is hard, so I'm looking to work around this on the Android client.
I figure these are options:
Intercept the JSON document before it reaches Gson and tweak the document, possibly with a customised Gson parser, or by intercepting the HTTP response.
Bypass the JSON parsing, and acquire the JSON document from Retrofit (I've yet to figure out how to do this, or if it's possible)
Use some feature of Retrofit I'm unaware of to map field names to a collection.
I'd appreciate help, especially if there's a quick and easy way to resolve this.
It turns out that Retrofit's use of Gson by default makes it fairly easy to add a custom deserialiser to handle the portion of the JSON document that was the problem.
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(ApiDefinition.BASE_URL)
.setConverter(getGsonConverter())
.build();
public Converter getGsonConverter() {
Gson gson = new GsonBuilder()
.registerTypeAdapter(RouteList.class, new RouteTypeAdapter())
.create();
return new GsonConverter(gson);
}
public class RouteTypeAdapter implements JsonDeserializer<RouteList> {
#Override
public RouteList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
Gson gson = new Gson();
RouteList routeList = new RouteList();
JsonObject jsonObject = json.getAsJsonObject();
for (Map.Entry<String,JsonElement> elementJson : jsonObject.entrySet()){
RouteList wardsRoutes = gson.fromJson(elementJson.getValue().getAsJsonArray(), RouteList.class);
routeList.addAll(wardsRoutes);
}
return routeList;
}
}
After calling RestService, don't use Model Name as argument, you have to use Default Response class from retrofit library.
RestService Method
#FormUrlEncoded
#POST(GlobalVariables.LOGIN_URL)
void Login(#Field("email") String key, #Field("password") String value, Callback<Response> callback);
Calling method in Activity
getService().Login(email, password, new MyCallback<Response>(context, true, null)
{
#Override
public void failure(RetrofitError arg0)
{
// TODO Auto-generated method stub
UtilitySingleton.dismissDialog((BaseActivity<?>) context);
System.out.println(arg0.getResponse());
}
#Override
public void success(Response arg0, Response arg1)
{
String result = null;
StringBuilder sb = null;
InputStream is = null;
try
{
is = arg1.getBody().in();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null)
{
sb.append(line + "\n");
result = sb.toString();
System.out.println("Result :: " + result);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
THIS WORKS FINE
I have this code block to read a json data that I am getting from FetchData.php file; My code looks like this:
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://10.0.2.2/mydummyproject/FetchData.php");
TextView textView = (TextView)findViewById(R.id.textView1);
try {
HttpResponse response = httpclient.execute(httppost);
String jsonResult = inputStreamToString(response.getEntity().getContent()).toString();
JSONObject object = new JSONObject(jsonResult);
String name = object.getString("name");
String verion = object.getString("version");
textView.setText(name + " - " + verion);
}
catch (JSONException e) {
e.printStackTrace();
}
Data from my PHP File FetchData.php
{"name":"John Doe","version":"Android 4.4"}
PROBLEM
I also have another type of data coming from FetchDataTwo.php
[{"name":"John Doe","version":"Android 4.4"}, {"name":"Seliana Gomez","version":"Android 4.1"}, {"name":"Nerdy Trumph","version":"Android 4.4"}]
Now the above one is also a json data that I have got by doing json_encode($multidimensional_array) in PHP file.
ISSUE
How to loop over this multidimensional encoded array from json. So that I can iterate over like this (json data by json data):
[NOTE: Below is the data that I need to fetch, I don't want to arrange in the displayed fashion. That's just for clarity and example]
Name | Version
John Doe | Android 4.4
Seliana Gomez | Android 4.1
Nerdy Trumph | Android 4.4
Basically as a logic something like this:
//Loop over each json object
for data in JSONObject:
// Print name and version
textView.setText(data.name + " - " + data.version)
It looks like all you have to do is iterate over the JSONArray
try {
JSONArray array = new JSONArray(inputString);
for (int i = 0; i < array.length(); i++) {
JSONObject jsonObject = array.optJSONObject(i);
// Json Object handling...
}
} catch (JSONException e) {
// handle
}
But really, using Gson should be way easier. It can parse the contents for you into a simple java object. You can annotate a POJO class with the field names and Gson does all the work.
public class NameVersionPair {
private interface Json {
String NAME = "name";
String VERSION = "version";
}
#SerializedName(Json.NAME)
private String mName;
#SerializedName(Json.VERSION)
private String mVersion;
public String getName() {
return mName;
}
public String getVersion() {
return mVersion;
}
}
Then use a Gson instance to parse your string automatically
Gson gson = new Gson();
NameVersionPair[] result = gson.fromJson(inputString, NameVersionPair[].class);