Expected BEGIN_ARRAY but was BEGIN_OBJECT when using GSON - java

Ok, I know that many of questions like that have been asked, but I have a specific question, which none of the others has. I want to know how I'd go on to parse following JSON file with GSON.
{
"BUYER": {
"IGN": "MGlolenstine",
"ProductID": "51"
},
"BUYER": {
"IGN": "MGlolenstine",
"ProductID": "55"
},
"BUYER": {
"IGN": "MGlolenstine",
"ProductID": "0"
},
"BUYER": {
"IGN": "MGlolenstine",
"ProductID": "51"
},
"BUYER": {
"IGN": "MGlolenstine",
"ProductID": "56"
}
}
because when I use this code
Scanner scanner = new Scanner( new File(path) );
String text = scanner.useDelimiter("\\A").next();
Gson gson = new GsonBuilder().create();
ArrayList<Purchases> p = gson.fromJson(new FileReader(path), Purchases.class);
for(int i = 0; i < p.size(); i++){
arg0.sendMessage(ChatColor.GOLD+"Player: "+p.get(i).BUYER.IGN);
arg0.sendMessage(ChatColor.GOLD+"ProductID: "+String.valueOf(p.get(i).BUYER.ProductID));
}
scanner.close();
I get the error
Caused by: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 2 column 12
Here just posting the classes I have for the JSON code
public class Purchases{
PlayerRank BUYER;
}
public class PlayerRank{
String IGN;
int ProductID;
}
The problem is probably me not knowing how the JSON arrays and objects look like.
Could someone please explain the difference between JSONArray and JSONObject in my JSON code?
Thank you in advance.
EDIT: So this is the fixed JSON
{
"buyers" : [
{ "IGN" : "MGlolenstine", "ProductID" : "51" },
{ "IGN" : "MGlolenstine", "ProductID" : "55" },
{ "IGN" : "MGlolenstine", "ProductID" : "0" },
{ "IGN" : "MGlolenstine", "ProductID" : "51" },
{ "IGN" : "MGlolenstine", "ProductID" : "56" }
]
}
Fixed Java code:
Scanner scanner = new Scanner( new File(path) );
String text = scanner.useDelimiter("\\A").next();
Gson gson = new GsonBuilder().create();
Purchases p = gson.fromJson(new FileReader(path), Purchases.class);
for(int i = 0; i < p.buyers.length; i++){
arg0.sendMessage(ChatColor.GOLD+"Player: "+p.buyers[i].IGN);
arg0.sendMessage(ChatColor.GOLD+"ProductID: "+String.valueOf(p.buyers[i].ProductID));
}
And lastly the classes:
public class Purchases{
PlayerRank buyers[];
}
public class PlayerRank{
String IGN;
int ProductID;
}
Thanks to everyone for the help!

JSON Objects are enclosed directly in curly brackets {} vs. JSON Arrays that are enclosed in square brackets [] inside JSON Objects.
The classes Purchases and PlayerRank should be defined in this way:
public class Purchases{
#SerializedName("buyers") protected ArrayList<PlayerRank> buyers;
...
}
public class PlayerRank{
#SerializedName("IGN") protected String ign;
#SerializedName("ProductID") protected int productId;
...
}
Note the SerializedName notation that lets you decouple the name of the objects/arrays in the json file from the names of your java properties.
The protected I added to the properties just makes it explicit what the original classes defaulted to in the original code.
The JSON file should be something like this:
{
"buyers" : [
{ "IGN": "MGlolenstine", "ProductID": "51"},
{ "IGN": "MGlolenstine", "ProductID": "55"},
...
{ "IGN": "MGlolenstine", "ProductID": "56"}
]
}
And to read the JSON into a variable:
Purchases p = gson.fromJson(new FileReader(path), Purchases.class);

Related

how to covert JSONObject to another Required JSONObect by mapping AccountId using java

**My result of JSONObject to convert as follows bellow code and have searched for many this how to convert using java but I converted that **
{
"result": {
"accountnames": [{
"accountName": "Hari",
"accountId": 878488
}, {
"accountName": "ravi",
"accountId": 878487
}],
"sales": [{
"accountSales": "89",
"accountId": 878488
}, {
"accountName": "98",
"accountId": 878487
}],
"countResult": [{
"accountResult": "945",
"accountId": 878488
}, {
"accountResult": "9452",
"accountId": 878489
}]
}
}
*and this is where the sample code to be converted *
{
"result": [{
"accountName": "Hari",
"accountSales": "89",
"accountResult": "945",
"accountId": 878488
},
{
"accountName": "ravi",
"accountSales": "98",
"accountId": 878487
},
{
"accountResult": "9452",
"accountId": 878489
}
]
}
My required JSON data has to be formatted as below
You need to group all the elements by accountId. You can use something like this depending on the json library that you are using.
Initialize the json object:
JSONObject rootJson = new JSONObject(json);
JSONObject resultJson = rootJson.getJSONObject("result");
Create a map to hold the objects by accountId:
Map<String, JSONObject> accountIds = new HashMap<>();
Then iterate for each key in the json, then for each element in the arrays and then for each property of the object inside the json:
Iterator mainKeys = resultJson.keys();
while (mainKeys.hasNext()) {
String key = (String) mainKeys.next();
JSONArray array = resultJson.getJSONArray(key);
for (int index = 0; index < array.length(); index++) {
JSONObject object = array.getJSONObject(index);
if (object.has("accountId")) {
String accountId = object.get("accountId").toString();
JSONObject accum = accountIds
.computeIfAbsent(accountId, (k) -> new JSONObject());
// depending on the json impl you can use putAll or similar
Iterator objKeys = object.keys();
while (objKeys.hasNext()) {
String property = (String) objKeys.next();
accum.put(property, object.get(property));
}
} else {
// does not have account id, ignore or throw
}
}
}
Finally create the json file and add the elements to the JSONArray:
JSONObject finalJson = new JSONObject();
finalJson.put("result", new JSONArray(accountIds.values()));
System.out.println(finalJson.toString());
(note: the json has an error in sales array accountName instead of accountSales)

JSON to JSON Transform of input sample using any existing java library/tools

Input:
{
"Student": {
"name" :"abc",
"id" : 588,
"class : "12"
}
}
Reqired Output:
{
"Student": {
"key" :"name",
"value":"abc",
"key" :"id",
"value":"588",
"key" :"class",
"value":"12"
}
}
Your output json invalid. Json object can not duplicate key .
You can use the library org.json and do something like this:
JSONObject jsonObject = new JSONObject(inputJson);
JSONObject outputJson = new JSONObject();
JSONArray array = new JSONArray();
for (Object key : jsonObject.keySet()) {
JSONObject item = new JSONObject();
String keyStr = (String)key;
Object keyvalue = jsonObj.get(keyStr);
item.put(keyStr, keyvalue);
array.put(item);
}
outputJson.put("Student", array);
System.out.println(json.toString());
Output :
{
"Student": [
{
"key": "name",
"value": "abc"
},
{
"key": "id",
"value": "588"
},
{
"key": "class",
"value": "12"
}
]
}
Similar to the other answer, the desired output JSON format is not valid.
The closest valid output would be
{
"Student" : [ {
"key" : "name",
"value" : "abc"
}, {
"key" : "id",
"value" : 588
}, {
"key" : "class",
"value" : "12"
} ]
}
This can be generated via Jolt with the following spec
[
{
"operation": "shift",
"spec": {
"Student": {
"name": {
"$": "Student[0].key",
"#": "Student[0].value"
},
"id": {
"$": "Student[1].key",
"#": "Student[1].value"
},
"class": {
"$": "Student[2].key",
"#": "Student[2].value"
}
}
}
}
]
This is easy to solve with JSLT if we assume the output is made valid JSON by making an array of key/value objects like the other respondents do.
The array function converts an object into an array of key/value objects exactly like you ask for, so the transform becomes:
{"Student" : array(.Student)}

Android JSON Parse Getting Array within Array

Seems like a simple problem, and I know there are multiple questions like this already. I'm trying to get JSON data from an Array within an Array.
I have a JSON Array as follows:
{
"results": [
{
"name": "John Doe",
"time": "09:00:00",
"claim": {
"date": "2015-08-06",
"comments": "Some comments"
}
},
{
"name": "Mary Smith",
"time": "10:00:00",
"claim": {
"date": "2015-08-06",
"comments": "Some comments"
}
}
}
]
}
I'm trying to parse all the information out of it, I'm able to get the name and time but i'm having trouble getting the data out of the claim array.
I have view multiple similar problems here on SO but none of their solutions fixed my problem.
Here is my Java Code:
#Override
protected void onPostExecute(JSONObject json) {
if (dialog.isShowing()) {
dialog.dismiss();
}
try {
// Getting JSON Array from URL
JSONArray android = json.getJSONArray(TAG_RESULTS);
for (int i = 0; i < android.length(); i++) {
JSONObject c = android.getJSONObject(i);
// Storing JSON items in Variables
String time = c.getString(TAG_TIME);
//For loop for claims array:
JSONArray claims = c.getJSONArray(TAG_CLAIM);
for (int j = 0; j < claims.length(); j++) {
JSONObject d = claims.getJSONObject(j);
String name = d.getString(TAG_NAME);
//other parsing and list view.
I'm getting this error:
org.json.JSONException: Value {"date": "2015-08-06","comments": "Some comments"} at claim of type org.json.JSONObject cannot be converted to JSONArray
08-06 12:43:27.436 17586-17586/com.murrion.navigationdrawer W/System.err﹕ at org.json.JSON.typeMismatch(JSON.java:100)
08-06 12:43:27.436 17586-17586/com.murrion.navigationdrawer W/System.err﹕ at org.json.JSONObject.getJSONArray(JSONObject.java:588)
On this line: JSONArray claims = c.getJSONArray(TAG_CLAIM);
I'm not sure what is going wrong, I'd greatly appreciate some help. Thanks
claim is not an array, but another object. If you want it to be an array, it should be something like this:
"claim": [
"date": "2015-08-06",
"comments": "Some comments"
]
(notice the [ ] instead of { })
If it's meant to be an object, then the code should read:
JSONObject claims = c.getJSONObject(TAG_CLAIM);
Try this
{
"results": [
{
"name": "John Doe",
"time": "09:00:00",
"claim": [
"date": "2015-08-06",
"comments": "Some comments"
]
},
{
"name": "Mary Smith",
"time": "10:00:00",
"claim": [
"date": "2015-08-06",
"comments": "Some comments"
]
}
]
}
Note: The problem in your json is clearly mentioned in the Error stack trace, which tells you that you are trying to parse the json object(within {...}) as json array(array should be within[...], not {...}). So please try to read the stack trace.
After removing the Extra } curly braces you json will be like this
{
"results" :
[
{
"name" : "John Doe",
"time" : "09:00:00",
"claim" :
{
"date" : "2015-08-06",
"comments" : "Some comments"
}
},
{
"name" : "Mary Smith",
"time" : "10:00:00",
"claim" :
{
"date" : "2015-08-06",
"comments" : "Some comments"
}
}
]
}
and to parse this json your code like this
#Override
protected void onPostExecute(JSONObject json)
{
if (dialog.isShowing()) {
dialog.dismiss();
}
try
{
// Getting JSON Array from URL
JSONArray android = json.getJSONArray(TAG_RESULTS);
for (int i = 0; i < android.length(); i++){
JSONObject c = android.getJSONObject(i);
// Storing JSON items in Variables
String time = c.getString(TAG_TIME);
String time = c.getString("name");
// for claims object:
JSONObject claims = c.getJSONObject(TAG_CLAIM);
String date= claims .getString("date");
String comments= claims .getString("comments");
//other parsing and list view.
}
}
catch(Exception e){}
}
as you are saying your json should be like this
{
"results" :
[{
"name" : "John Doe",
"time" : "09:00:00",
"claim" : [{
"date" : "2015-08-06",
"comments" : "Some comments"
}
]
}, {
"name" : "Mary Smith",
"time" : "10:00:00",
"claim" : [{
"date" : "2015-08-06",
"comments" : "Some comments"
}
]
}
]
}
and your code like this
#Override
protected void onPostExecute(JSONObject json)
{
if (dialog.isShowing()) {
dialog.dismiss();
}
try
{
// Getting JSON Array from URL
JSONArray android = json.getJSONArray(TAG_RESULTS);
for (int i = 0; i < android.length(); i++){
JSONObject c = android.getJSONObject(i);
// Storing JSON items in Variables
String time = c.getString(TAG_TIME);
String time = c.getString("name");
// for claims object:
JSONArray claims = c.getJSONArray(TAG_CLAIM);
for (int j = 0; j < claims.length(); j++) {
JSONObject d = claims.getJSONObject(j);
String date= d.getString("date");
String comments= d.getString("comments");
//other parsing and list view.
}
}
}
catch(Exception e){}
}

Using GSON to parse a JSON array

I have a JSON file like this:
[
{
"number": "3",
"title": "hello_world",
}, {
"number": "2",
"title": "hello_world",
}
]
Before when files had a root element I would use:
Wrapper w = gson.fromJson(JSONSTRING, Wrapper.class);
code but I can't think how to code the Wrapper class as the root element is an array.
I have tried using:
Wrapper[] wrapper = gson.fromJson(jsonLine, Wrapper[].class);
with:
public class Wrapper{
String number;
String title;
}
But haven't had any luck. How else can I read this using this method?
P.S I have got this to work using:
JsonArray entries = (JsonArray) new JsonParser().parse(jsonLine);
String title = ((JsonObject)entries.get(0)).get("title");
But I would prefer to know how to do it (if possible) with both methods.
Problem is caused by comma at the end of (in your case each) JSON object placed in the array:
{
"number": "...",
"title": ".." , //<- see that comma?
}
If you remove them your data will become
[
{
"number": "3",
"title": "hello_world"
}, {
"number": "2",
"title": "hello_world"
}
]
and
Wrapper[] data = gson.fromJson(jElement, Wrapper[].class);
should work fine.
Gson gson = new Gson();
Wrapper[] arr = gson.fromJson(str, Wrapper[].class);
class Wrapper{
int number;
String title;
}
Seems to work fine. But there is an extra , Comma in your string.
[
{
"number" : "3",
"title" : "hello_world"
},
{
"number" : "2",
"title" : "hello_world"
}
]
public static <T> List<T> toList(String json, Class<T> clazz) {
if (null == json) {
return null;
}
Gson gson = new Gson();
return gson.fromJson(json, new TypeToken<T>(){}.getType());
}
sample call:
List<Specifications> objects = GsonUtils.toList(products, Specifications.class);
Wrapper[] data = gson.fromJson(jElement, Wrapper[].class);

Get sub-array from JSON

I parsing some data from a json file. Here is my JSON File.
[
{
"topic": "Example1",
"contact": [
{
"ref": [
1
],
"corresponding": true,
"name": "XYZ"
},
{
"ref": [
1
],
"name": "ZXY"
},
{
"ref": [
1
],
"name": "ABC"
},
{
"ref": [
1,
2
],
"name":"BCA"
}
] ,
"type": "Presentation"
},
{
"topic": "Example2",
"contact": [
{
"ref": [
1
],
"corresponding": true,
"name": "XYZ"
},
{
"ref": [
1
],
"name": "ZXY"
},
{
"ref": [
1
],
"name": "ABC"
},
{
"ref": [
1,
2
],
"name":"BCA"
}
] ,
"type": "Poster"
}
]
I can fetch and store data one by one. Like this one
JSONArray getContactsArray = new JSONArray(jsonObject.getString("contact"));
for(int a =0 ; a < getContactsArray.length(); a++)
{
JSONObject getJSonObj = (JSONObject)getContactsArray.get(a);
String Name = getJSonObj.getString("name");
}
1)Now, my question is there any way to get all name values for each array with single query.
2) Can I get all those values in an Array ?
Please correct me, if I am doing anything wrong. Thank you.
Iteration cannot be avoided here as org.json and other Json parsers as well provide random access to objects but not to their properties collectively (as a collection). So, you can't query something like "all name properties of all contact objects" unless you probably get a Json parser like Gson to unmarshall it that way.
But, that's too much to just avoid a for loop when you can definitely shorten the parse by making use of the appropriate API methods to avoid unnecessary object casts.
JSONArray contacts = jsonObject.getJSONArray("contact");
String[] contactNames = new String[contacts.length()];
for(int i = 0 ; i < contactNames.length; i++) {
contactNames[i] = contacts.getJSONObject(i).getString("name");
}
Better to use a json parser such as GSon or Jackson to marshall your json to a java object. Then you can write utitlity method in your java class to retrieve all the names in that object.
Try this:
Create JSONObject of your file and try to get array of all names and iterate it to get all values.
public static String[] getNames(JSONObject jo) {
int length = jo.length();
if (length == 0) {
return null;
}
Iterator i = jo.keys();
String[] names = new String[length];
int j = 0;
while (i.hasNext()) {
names[j] = (String) i.next();
j += 1;
}
return names;
}

Categories