Problem in Parsing JSON in Android - java

Hello friends i am having problem in parsing jSON web services data
I have the following set of data i got from my web services
[{"store_id":"81","store_name":"Mayo - Castlebar McDrive","store_type":"Drive-Thru",
"vouchers_available":"Vouchers available","store_limit":"10","distance":"8123.33 km",
"latitude":"53.8501090162671","longitude":"-9.29713726043701","image_name":"http:\/\/www.mcfinder.ie\/admin\/images\/stores\/default.png",
"voucher_count":"2","is_open":"Restaurant Open","attributes":[{"attribute_name":"Wi-Fiiiii",
"image_name":"http:\/\/www.mcfinder.ie\/admin\/images\/attributes\/t_wifi_icon.gif"},{"attribute_name":"Cashless",
"image_name":"http:\/\/www.mcfinder.ie\/admin\/images\/attributes\/t_cashless_icon.gif"},
{"attribute_name":"McDrive","image_name":"http:\/\/www.mcfinder.ie\/admin\/images\/attributes\/car_icon.png"}]}]
and i m using this code to parse the DATA but i am getting the error
Please friends i am new in JSON Web services guide me what am i doing wrong.
CODE:
JSONObject jObject = new JSONObject(data);
JSONArray array = jObject.getJSONArray("attributes");
ERROR:
07-19 23:43:02.437: WARN/System.err(674): org.json.JSONException: A JSONObject text must begin with '{' at character 2 of
M waiting for some positive response and guidelines
Thanks

If you're going to work with JSON data, I recommend reviewing the JSON introduction at http://json.org, until it is thoroughly understood. Luckily, JSON is a relatively simple data format, and becoming comfortable with it comes quickly.
To the specific problem in the original question, note that the outer-most structure of the JSON data is an array. So, it needs to be read as an array -- not as an object.
Here's a brief description of the complete JSON structure.
An array with one element that is an unnamed object. The unnamed object has twelve elements, eleven of which are strings, and one of which, named "attributes", is an array of three objects. Each object in the "attributes" array has two string elements.
So, if you want the "attributes" array, first read in the entire contents as an array, then get the first component of the array as an object, then get the "attributes" element from that object as an array. Following is an example of doing this.
import java.math.BigDecimal;
import java.net.URI;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONObject;
public class Foo
{
public static void main(String[] args) throws Exception
{
JSONArray outerArray = new JSONArray("[{\"store_id\":\"81\",\"store_name\":\"Mayo - Castlebar McDrive\",\"store_type\":\"Drive-Thru\",\"vouchers_available\":\"Vouchers available\",\"store_limit\":\"10\",\"distance\":\"8123.33 km\",\"latitude\":\"53.8501090162671\",\"longitude\":\"-9.29713726043701\",\"image_name\":\"http:\\/\\/www.mcfinder.ie\\/admin\\/images\\/stores\\/default.png\",\"voucher_count\":\"2\",\"is_open\":\"Restaurant Open\",\"attributes\":[{\"attribute_name\":\"Wi-Fiiiii\",\"image_name\":\"http:\\/\\/www.mcfinder.ie\\/admin\\/images\\/attributes\\/t_wifi_icon.gif\"},{\"attribute_name\":\"Cashless\",\"image_name\":\"http:\\/\\/www.mcfinder.ie\\/admin\\/images\\/attributes\\/t_cashless_icon.gif\"},{\"attribute_name\":\"McDrive\",\"image_name\":\"http:\\/\\/www.mcfinder.ie\\/admin\\/images\\/attributes\\/car_icon.png\"}]}]");
JSONObject object = outerArray.getJSONObject(0);
JSONArray attributes = object.getJSONArray("attributes");
for (int i = 0, length = attributes.length(); i < length; i++)
{
JSONObject attribute = attributes.getJSONObject(i);
System.out.printf("attribute name=%s, image=%s\n", attribute.getString("attribute_name"), attribute.getString("image_name"));
}
}
}
If you're not stuck using the built-in JSON API that Android provides, I highly recommend switching to Jackson, which makes it very easy to read and write arbitrarily complex JSON with Java. Following is an example of using it.
import java.io.File;
import java.math.BigDecimal;
import java.net.URI;
import java.util.List;
import org.codehaus.jackson.map.ObjectMapper;
public class Foo
{
public static void main(String[] args) throws Exception
{
ObjectMapper mapper = new ObjectMapper();
Store[] stores = mapper.readValue(new File("input.json"), Store[].class);
Store store = stores[0];
List<Attribute> attributes = store.attributes;
for (Attribute attribute : attributes)
{
System.out.printf("attribute name=%s, image=%s\n", attribute.attribute_name, attribute.image_name);
}
// output:
// attribute name=Wi-Fiiiii, image=http://www.mcfinder.ie/admin/images/attributes/t_wifi_icon.gif
// attribute name=Cashless, image=http://www.mcfinder.ie/admin/images/attributes/t_cashless_icon.gif
// attribute name=McDrive, image=http://www.mcfinder.ie/admin/images/attributes/car_icon.png
}
}
class Store
{
public String store_id;
public String store_name;
public String store_type;
public String vouchers_available;
public String store_limit;
public String distance;
public BigDecimal latitude;
public BigDecimal longitude;
public URI image_name;
public int voucher_count;
public String is_open;
public List<Attribute> attributes;
}
class Attribute
{
public String attribute_name;
public URI image_name;
}

The answer by #Richard aka cyberkiwi for this question should be the answer for your question.
He says:
You may be passing the STRING to JSONObject with leading spaces. Try trimming
JSONObject allCDs = new JSONObject(objectString.replace(/^\s+/,""));
EDIT: I thought this was javascript. Try trimming it using Java code instead
JSONObject allCDs = new JSONObject(objectString.trim());
If that still doesn't work, then show what the first character from the string is:
System.out.println((int)objectString.trim().charAt(0));
You should be expecting 123, the curly braces. In fact, check the entire content
System.out.println((int)objectString); // or
System.out.println((int)objectString.trim());
You could also try cutting everything before the { in the string
JSONObject allCDs = new JSONObject(objectString.substring(objectString.indexOf('{')));

If you're taking the Udacity android course and encountering this error for the quakereport/DidUfeelIt app then change the URL and try with some other URL your problem will be solved. Eg:- The URL provided by during the course was "http://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime=2012-01-01&endtime=2012-12-01&minmagnitude=6"
Then I was getting the same error that is "problem parsing the JSON" So I tried different URL: https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/4.5_day.geojson
And it worked..!! Always try to get the latest URL's from the USGS website during the course.

Related

Is there a way in Java to get the line number using the jsonpointer from a json file

I have a case wherein I have the jsonpointer and the swagger json file. I need to get the line number to which the jsonpointer is pointing to.
Is there a way to do so, I used ObjectMapper, I get the jsonNode, I also saw in the the code, the JsonParser has the information about the line number when the json file is parsed, I there a way to get the line number for each ObjectNode, or just pass the jsonPointer and get the line number.
Below is the code:
public class JsonPointerUtil {
static ObjectMapper om = new ObjectMapper();
private JsonNode jsonNode;
public JsonPointerUtil(File json) throws IOException {
jsonNode = com.xyz.util.JsonPointerUtil.om.readTree(json);
}
public String getJsonBlockForPointer(String jsonPtr) {
if (StringUtils.isEmpty(jsonPtr))
return null;
JsonNode at = jsonNode.at(jsonPtr);
return at.toString();
}
}
So in getJsonBlockForPointer method using the pointer I get the json node, The json node is the exact json block pointed by the pointer, I need the line number also of the pointed json block, Is there a way I can get that.
My requirement is, the line number is used by UI side code, there are multiple UI apps which call the same backend service, On UI side, the jsonPointer library gives me all the information (line,col no, agiainst each jsonPointer), but as there are multiple UI apps consuming the same service, I want to send all theinfo from backend.
posting after long time, we ultimately ended up using javascript only, we called the javascript from java and passing the relevant details.
we basically used
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
Invocable inv = (Invocable) engine;
long start = new Date().getTime();
Gson gson=new Gson();
parse = inv.invokeFunction("getLineNumbers", jsonPointers, swaggerAsString);
called the javascript file from java.

GSON get string from complex json

I am trying to parse the JSON from this link: https://api.guildwars2.com/v2/items/56 , everything fine until i met the line: "infix_upgrade":{"attributes":[{"attribute":"Power","modifier":4},{"attribute":"Precision","modifier":3}]} ...
If i dont get this wrong: infix_upgradehas 1 element attributes inside him. attributes has 2 elements with 2 other inside them. Is this a 2 dimension array?
I have tried (code too long to post):
JsonObject _detailsObject = _rootObject.get("details").getAsJsonObject();
JsonObject infix_upgradeObject = _detailsObject.get("infix_upgrade").getAsJsonObject();
JsonElement _infix_upgrade_attributesElement = infix_upgradeObject.get("attributes");
JsonArray _infix_upgrade_attributesJsonArray = _infix_upgrade_attributesElement.getAsJsonArray();
The problem is that I dont know what to do next, also tried to continue transforming JsonArray into string array like this:
Type _listType = new TypeToken<List<String>>() {}.getType();
List<String> _details_infusion_slotsStringArray = new Gson().fromJson(_infix_upgrade_attributesJsonArray, _listType);
but im getting java.lang.IllegalStateException: Expected STRING but was BEGIN_OBJECT which i guess comes from the attributes...
With a proper formatting (JSONLint, for example, checks if the JSON data is valid and does the formatting, which makes the structure more clear than what the GW link gives), attributes looks actually like this:
"attributes": [
{
"attribute": "Power",
"modifier": 4
},
{
"attribute": "Precision",
"modifier": 3
}
]
So it's an array of JsonObject and each object as two key-value pairs. This is why the parser throws an error because you require that this array contains only String which is not the case.
So the actual type is:
Type _listType = new TypeToken<List<JsonObject>>(){}.getType();
The problem is that I dont know what to do next
Hold on. You are using Gson and Java is an OO language so I suggest you to create classes.
This would be easier for you to fetch the datas afterward and for the parsing since you just need to provide the class of the actual class the JSON data represents to the parser (some edge-cases could be handled by writing a custom serializer/deserializer).
The data is also better typed than this bunch of JsonObject/JsonArray/etc.
This will give you a good starting point:
class Equipment {
private String name;
private String description;
...
#SerializedName("game_types")
private List<String> gameTypes;
...
private Details details;
...
}
class Details {
...
#SerializedName("infix_upgrade")
private InfixUpgrade infixUpgrade;
...
}
class InfixUpgrade {
private List<Attribute> attributes;
...
}
class Attribute {
private String attribute;
private int modifier;
...
}
and then just give the type to the parser:
Equipment equipment = new Gson().fromJson(jsonString, Equipment.class);
Hope it helps! :)

Convert Java List to Javascript Array

I have the following java code in my Android application and wanted a way to convert the Java list to an array that can be used in javascript:
Java:
public void onCompleted(List<GraphUser> users, Response response) {
for(int i = 0; i < users.size(); i++)
{
//add to an array object that can be used in Javascript
webView.loadUrl("javascript:fetchFriends(arrObj)");
}
}
Javascript:
//this is how I want to be able to use the object in Javascript
function parseFriends(usersObjectFromJava){
var users = [];
for (var i = 0; i < usersObjectFromJava.length; i++) {
var u = {
Id: usersObjectFromJava[i].id + "",
UserName: usersObjectFromJava[i].username,
FirstName: usersObjectFromJava[i].first_name,
LastName: usersObjectFromJava[i].last_name,
};
users[i] = u;
}
}
Could some help me with the Java code to create the usersObjectFromJava so that it can be used in javascript?
Use GSON
to convert java objects to JSON string, you can do it by
Gson gson = new Gson();
TestObject o1 = new TestObject("value1", 1);
TestObject o2 = new TestObject("value2", 2);
TestObject o3 = new TestObject("value3", 3);
List<TestObject> list = new ArrayList<TestObject>();
list.add(o1);
list.add(o2);
list.add(o3);
gson.toJson(list) will give you
[{"prop1":"value1","prop2":2},{"prop1":"value2","prop2":2},{"prop1":"value3","prop2":3}]
Now you can use JSON.parse(), to deserialize from JSON to Javascript Object.
I would assume doing this:
Java:
public void onCompleted(List<GraphUser> users, Response response) {
JSONArray arr = new JSONArray();
JSONObject tmp;
try {
for(int i = 0; i < users.size(); i++) {
tmp = new JSONObject();
tmp.put("Id",users.get(i).id); //some public getters inside GraphUser?
tmp.put("Username",users.get(i).username);
tmp.put("FirstName",users.get(i).first_name);
tmp.put("LastName",users.get(i).last_name);
arr.add(tmp);
}
webView.loadUrl("javascript:fetchFriends("+arr.toString()+")");
} catch(JSONException e){
//error handling
}
}
JavaScript:
function fetchFriends(usersObjectFromJava){
var users = usersObjectFromJava;
}
You will have to change the Java-Code a bit (i.e. using public getters or add more/less information to the JSONObjects.
JSON is included in Android by default, so no external libraries are necessary.
I hope i understood your problem.
Small thing i came across: you where using fetchFriends in Java but its called parseFriends in Javascript, I renamed them to fetchFriends
You can use Gson Library.
Gson gson = new GsonBuilder().create();
JsonArray jsonArray = gson.toJsonTree(your_list, TypeClass.class).getAsJsonArray();
http://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/Gson.html
Use Jackson.
You'll need to add an " #JsonProperty" annotation to every property of your POJOs you want to pass, then do something like this:
String respStr = "";
for(Object whatever: MyList)
{
JSONObject dato = new JSONObject();
dato.put("FirstField", whatever.SomeData());
dato.put("SecondField", whatever.SomeData2());
StringEntity entity = new StringEntity(dato.toString());
post.setEntity(entity);
webView.loadUrl("javascript:fetchFriends("+entity+")");
}
I am not sure why no answer mentioned about jaxb. I am just thinking jaxb would be a good fit for this type of problems...
For a sample style of annotated jaxb class, please find this.
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class ResponseAsList {
private List < Object > list = new ArrayList < Object > ();
public ResponseAsList() {
// private default constructor for JAXB
}
public List < Object > getList() {
return list;
}
public void setList(List < Object > list) {
this.list = list;
}
}
You will stuff your data in these lists and you will marshal either in xml or a json. After you get a json to the client, you can do a var myArray = JSON.parse(response);...
Although I typically advocate using something like GSON or Jackson to do JSON conversions for you, its pretty easy to roll your own if you're in a limited environment (like Android) and don't want to bundle a bunch of dependencies.
public class JsonHelper {
public static String convertToJSON(List<GraphUser> users) {
StringBuilder sb = new StringBuilder();
for (GraphUser user : users) {
sb.append(convertToJSON(user));
}
return sb.toString();
}
public static String convertToJSON(GraphUser user) {
return new StringBuilder()
.append("{")
.append("\"id\":").append(user.getId()).append(",")
.append("\"admin\":").append(user.isAdmin() ? "true" : "false").append(",")
.append("\"name\":\"").append(user.getName()).append("\",")
.append("\"email\":\"").append(user.getEmail()).append("\"")
.append("}")
.toString();
}
}
You could obviously make a toJSON() method on GraphUser to put the logic if you prefer. Or use an injectable json helper library instead of static methods (I would). Or any number of other abstractions. Many developers prefer to separate representation of model objects into their own object, myself included. Personally, I might model it something like this if I wanted to avoid dependencies:
interface Marshaller<F,T> with methods T marshall(F obj) and F unmarshall(T obj)
interface JsonMarshaller<F> extends Marshaller<String>
class GraphUserMarshaller implements JsonMarshaller<GraphUser>
class GraphUserCollectionMarshaller implements JsonMarshaller<Collection<GraphUser>> which could do type-checking or use the visitor pattern or something to determine the best way to represent this type of collection of objects.
Along the way, I'm sure you'll find some repeated code to extract to super- or composite- classes, particularly once you start modeling collection marshallers this way. Although this can get to be pretty verbose (and tedious), it works particularly well in resource-constrained environments where you want to limit the number of libraries on which you depend.
You can use the Google Gson library (http://code.google.com/p/google-gson/) to convert the Java List Object to JSON. Ensure that the right fields are set like ID, UserName, FirstName, etc and on the java script side that same code would work.
Its just an example, First add javascript interface. It will be a bridge between javascript and java code.
webView.addJavascriptInterface(new JSInterface(), "interface");
In javascript you can add like this,
"window.interface.setPageCount(pageCount1);"
The interface is a keyword in common between java and javascript. create a class JSInterace and define a method setPageCount(int a). The script will return a value, and you can use that value in your java method

How to add two JSON formatted Java Strings together?

I have two JSON Format Strings
{"user1":{"Iden":4,"nID":1},"user2":{"Iden":5,"nID":1}} // String A JSON
{"user1":{"Iden":4,"nID":1},"user3":{"Iden":6,"nID":1},"user2":{"Iden":5,"nID":1}}
In the below program these above JSON are formatted by Eclipse IDE
This is my program:
import java.util.Map;
import org.codehaus.jackson.type.TypeReference;
import com.tradeking.at.util.JsonHelper;
public class Hi {
private static JsonHelper jsonHelper = JsonHelper.getInstance();
public static void main(String[] args) throws Exception {
Map<String, Tracker> totalCusts = null;
String A = "{\"user1\":{\"Iden\":4,\"nID\":1},\"user2\":{\"Iden\":5,\"nID\":1}}";
String B = "{\"user1\":{\"Iden\":4,\"nID\":1},\"user3\":{\"Iden\":6,\"nID\":1},\"user2\":{\"Iden\":5,\"nID\":1}}";
String totalString = A+B;
if (null != totalString) {
totalCusts = (Map<String, Tracker>) jsonHelper.toObject(
totalString, new TypeReference<Map<String, Tracker>>() {
});
}
System.out.println(totalCusts);
}
}
Tracker.java:
import org.json.JSONObject;
public class Tracker extends JSONObject{
}
When i ran the above , the Output is
{user1={}, user2={}}
if I use this:
String totalString = B + A ;
The O/p is:
{user1={}, user3={}, user2={}}
Please let me know how I can add two JSON Strings??
At the top-level, a JSON document is always a single object, array, or value. By just concatenating the two strings together, you're violating this principal. A simple workaround would be to join the two values together in an array:
String totalString = "[" + A + ", " + B + "]";
And then parse as such. Or you could simply parse each JSON document one at a time, and then append or merge your results (I suspect you want to merge them, via Map.putAll).
Given that the values for your userN keys are empty, you probably have a bug in your JsonHelper class, but that's hard to say without seeing the code.

Deserialization of generic collections with Gson

I have some difficulties with json deserialization using GSon and I hope somebody can help me.
I want to deserialize the following json snippet:
{
"fieldA": "valueA",
"myCollection": {
"AnotherClass": [
{
"objectAfieldA": "valueB",
"objectAfieldB": "valueC"
},
{
"objectAfieldA": "valueD",
"objectAfieldB": "valueE"
}
]
}
}
the corresponding overall class has following fields:
...
String fieldA;
List<AnotherClass> = new ArrayList<AnotherClass>();
....
Now, my problem is that when I deserialize, using fromJson(jsonSample, resultContainer.class), without the List<T> element, everything is good, but I get a NullPointerException when I include the contained list. I've read about how to deal with collections of generic types and the use of TypeToken, but I can't apply this knowledge when my collection is part of another class…
I really would appreciate any help to solve this.
The solution for deserealizing the unnamed JSON array is quite simple:
List<resultContainer> lres = gson.fromJson(new FileReader("input.json"), new TypeToken<List<resultContainer>>(){}.getType());
When deserializing, you only need to use the TypeToken if the outer-most structure to be deserialized into is a generic collection. This is not the case for the example in the original question. So, use of a TypeToken is unnecessary.
The issue appears to be that the JSON structure does not match the Java structure attempting to be bound to.
The JSON structure defines
an object with two elements
element 1 is a string named "fieldA",
element 2 is an object named "myCollection", which has one element
the one element is an array named "AnotherClass", composed of objects with two elements
element 1 is a string named "objectAfieldA",
element 2 is a string named "objectAfieldB"
So, define a Java data structure to match that, and deserialization will work very simply, without any custom processing necessary. If such a matching Java structure is not provided, then custom deserialization is necessary.
Here is such a working example using the names and types from the original question.
import java.io.FileReader;
import com.google.gson.Gson;
public class Foo
{
public static void main(String[] args) throws Exception
{
Gson gson = new Gson();
resultContainer result = gson.fromJson(new FileReader("input.json"), resultContainer.class);
System.out.println(gson.toJson(result));
}
}
class resultContainer
{
String fieldA;
MyCollectionContainer myCollection;
}
class MyCollectionContainer
{
SomeOtherClass[] AnotherClass;
}
class SomeOtherClass
{
String objectAfieldA;
String objectAfieldB;
}

Categories

Resources