I'm trying to unmarshal using MOXy a json with the following structure:
[
{
"page": 1,
"pages": 1
},
[
{
"indicator": {
"id": "IC.BUS.EASE.XQ",
"value": "Ease of doing business index"
},
"country": {
"id": "1A",
"value": "Arab World"
},
"value": "113.952380952381",
"date": "2014"
},
...
]
]
The first element of the array is an object and the second element is another array of complex elements. I've really searched here at SO and the MOXy documentation for a simmilar example without any success.
My best attempt at mapping the json document to JAVA classes is as follows. The root class is CountryDataResponse (getters & setters ommited):
#XmlRootElement
#XmlType(propOrder ={"paginationInfo", "dataArray"})
public class CountryDataResponse {
private DataArray dataArray;
private PaginationInfo paginationInfo;
}
(I can see this is going to fail, because it isn't an array, but I'm completly lost.)
PaginationInfo class models the first element of the root array and DataArray class wraps the second element, which is an Array of Data class elements. Additionally, I've created the Indicator and Country classes for the complex types inside each Data element.
The main classes (Indicator and Country ommited):
#XmlRootElement(name = "paginationInfo")
#XmlAccessorType(XmlAccessType.FIELD)
public class PaginationInfo {
private int page;
private int pages;
}
#XmlRootElement( name = "dataArray" )
public class DataArray {
List<Data> datas;
}
#XmlRootElement(name="data")
#XmlAccessorType(XmlAccessType.FIELD)
public class Data {
private Indicator indicator;
private Country country;
private String date;
private double value;
}
Now, debugging the following code:
public static void main(String args[]) {
String test = "[{\"page\": 1,\"pages\": 1,\"per_page\": \"1000\",\"total\": 248},"
+ "["
+ "{\"indicator\": {\"id\": \"NY.GDP.MKTP.CD\",\"value\": \"GDP (current US$)\"},"
+ "\"country\": {\"id\": \"1A\",\"value\": \"Arab World\"},"
+ "\"value\": \"2853079422103.94\","
+ "\"decimal\": \"1\","
+ "\"date\": \"2013\"},"
+ "{\"indicator\": {\"id\": \"NY.GDP.MKTP.CD\",\"value\": \"GDP (current US$)\"},"
+ "\"country\": {\"id\": \"S3\",\"value\": \"Caribbean small states\"},"
+ "\"value\": \"67033118185.1864\","
+ "\"decimal\": \"1\","
+ "\"date\": \"2013\"}"
+ "]]";
JAXBContext jc = JAXBContext.newInstance(CountryDataResponse.class, Country.class, Data.class, DataArray.class, Indicator.class, PaginationInfo.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON);
unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
Object res = unmarshaller.unmarshal(json, CountryDataResponse.class);
}
The res object (of class JAXBElement) has a value of type ArrayList. The first element of the array is an object of class CountryDataResponse (it should be PaginationInfo), the second is another ArrayList with elements of class CountryDataResponse, too (they should be Data instances).
Can anyone help me, please, or it is simply a malformed json and it can't be automatically unmarshalled correctly?
Thank you in advance.
Although the JSON is valid I would suggest changing the structure, something along the lines of:
{
"paginationInfo": {
"page": 1,
"pages": 1
},
"dataArray": [
{
"indicator": {
"id": "IC.BUS.EASE.XQ",
"value": "Ease of doing business index"
},
"country": {
"id": "1A",
"value": "Arab World"
},
"value": "113.952380952381",
"date": "2014"
}
]
}
This will allow you to extract the data you wish using the 'key' name which is how JSON is intended to be used.
Another approach would be to embed the data array within the paged object:
{
"page": 1,
"pages": 1,
"dataArray": [
{
"indicator": {
"id": "IC.BUS.EASE.XQ",
"value": "Ease of doing business index"
},
"country": {
"id": "1A",
"value": "Arab World"
},
"value": "113.952380952381",
"date": "2014"
}
]
}
This approach would allow you to create a generic page wrapper which could come in useful if you have multiple formats you would like to page.
Hope this helps.
Thanks to a MOXy's feature added in version 2.6, it's possible to unmarshal from javax.json.JsonStructure, javax.json.JsonObject and javax.json.JsonArray.
Using this feature I've managed to unmarshal the different parts of the original JSON to two objects: a PaginationInfo instance and an ArrayList of Data. These objects can then be used to configure an instance of CountryDataResponse, although it wouldn't be necessary as this class was created only to try to unmarshal directly from the JSON, in the first place.
public static CountryDataResponse javaSevenMode(String jsonString)
throws PropertyException, JAXBException {
Unmarshaller unmarshaller = JAXB_CONTEXT.createUnmarshaller();
unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON);
unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
StringReader sr = new StringReader(jsonString);
JsonReader jsonReader = Json.createReader(sr);
JsonArray rootArray = jsonReader.readArray();
JsonObject paginationInfoJO = rootArray.getJsonObject(0);
JsonStructureSource paginationInfoJSS = new JsonStructureSource(paginationInfoJO);
PaginationInfo pi = unmarshaller.unmarshal(paginationInfoJSS, PaginationInfo.class).getValue();
JsonArray dataJArray = rootArray.getJsonArray(1);
JsonStructureSource dataArrayJSS = new JsonStructureSource(dataJArray);
List<Data> datas
= (List<Data>) unmarshaller.unmarshal(dataArrayJSS, Data.class)
.getValue();
DataArray da = new DataArray();
da.setDatas(datas);
CountryDataResponse cdr = new CountryDataResponse();
cdr.setDataArray(da);
cdr.setPaginationInfo(pi);
return cdr;
}
Thanks to #blaise-doughan for inspiration (see http://blog.bdoughan.com/2013/07/eclipselink-moxy-and-java-api-for-json.html)
Related
I've been having some problems iterating through a JSON object in Java.
Specifically, I'd like to save each value for "name" to the string array "nameList". I've looked up how to do this, and I haven't found a way for this situation.
String[] nameList = new String[]{};
{
"data": {
"Narray": {
"0":
{
"_id": "001",
"name": "studio",
"date": "02141992"
},
"1":
{
"_id": "002",
"name": "venue",
"date": "09041999"
}
}
}
Ideally you'd want Narray to be an actual JSON array, enclosed in [], with each element being another object, containing the property you need, like this:
{
"Narray": [
{
"_id": "001",
"name": "studio",
"date": "02141992"
},
{
"_id": "002",
"name": "venue",
"date": "09041999"
}
]
}
Then you can use jackson to decode the JSON string into a POJO structure. Once you have the objects, you can iterate over the array and retrieve the property you need into a list.
I assume that you only want to save each value of name into a String[] (string array), so you don't need to deserialize the JSON string to POJO, just use basic API to achieve what you want as follows:
BTW, your JSON string is invalid, you miss a right bracket.
ObjectMapper mapper = new ObjectMapper();
JsonNode nArray = mapper.readTree(jsonStr).get("data").get("Narray");
String[] nameList = new String[nArray.size()];
for (int i = 0; i < nArray.size(); i++) {
nameList[i] = nArray.get(String.valueOf(i)).get("name").asText();
}
System.out.println(Arrays.toString(nameList));
Console output:
[studio, venue]
I am having trouble parsing a simple json in java. Here is the sample json.
[
{
"politics": [
{
"type": "admin2",
"friendly_type": "country",
"name": "United States",
"code": "usa"
},
{
"type": "admin6",
"friendly_type": "county",
"name": "Gratiot",
"code": "26_057"
},
{
"type": "constituency",
"friendly_type": "constituency",
"name": "Eighth district, MI",
"code": "26_08"
},
{
"type": "admin6",
"friendly_type": "county",
"name": "Clinton",
"code": "26_037"
},
{
"type": "admin4",
"friendly_type": "state",
"name": "Michigan",
"code": "us26"
},
{
"type": "constituency",
"friendly_type": "constituency",
"name": "Fourth district, MI",
"code": "26_04"
}
],
"location": {
"latitude": 43.111976,
"longitude": -84.71275
}
}
]
Now this gives me the correct json index.
JSONParser parser = new JSONParser();
Object obj = parser.parse(output);
JSONArray array = (JSONArray)obj;
String jsonobj = array.get(0).toString();
{"politics":[{"code":"usa","name":"United States","type":"admin2","friendly_type":"country"},{"code":"26_057","name":"Gratiot","type":"admin6","friendly_type":"county"},{"code":"26_08","name":"Eighth district, MI","type":"constituency","friendly_type":"constituency"},{"code":"26_037","name":"Clinton","type":"admin6","friendly_type":"county"},{"code":"us26","name":"Michigan","type":"admin4","friendly_type":"state"},{"code":"26_04","name":"Fourth district, MI","type":"constituency","friendly_type":"constituency"}],"location":{"latitude":43.111976,"longitude":-84.71275}}
But I cant seem to get the attribute that I want from it.
JSONObject obj1 = new JSONObject(jsonobj);
String n = obj1.getString("admin4");
System.out.println(n);
All that I need from this json is the state which is Michigan. Where am I wrong?
Help would be really appreciated.
First, array.get(0) will get you the first element from the main array. This first element is a JSON object that has two properties politics and location. You seem to be interested in a value that is inside the array value of the politics property. You'll have to use this ((JSONArray)((JSONObject)array.get(0)).get("politics")) to get that array.
Second, admin4 is not a property it is actually a value of the type property. You'll have to loop through the array to find it.
Here is a complete example:
JSONParser parser = new JSONParser();
Object obj = parser.parse(output);
JSONArray array = (JSONArray)obj;
JSONArray politics = ((JSONObject)array.get(0)).get("politics"));
JSONObject obj = null;
for(int i = 0; i < politics.size(); i++){
if(((JSONObject)politics.get(i)).getString("type").equals("admin4")){
obj = ((JSONObject)politics.get(i));
}
}
if(obj != null){
// Do something with the object.
}
It seems that you're using the simple json library. I don't remember exactly if it is .get("politics") or .getJSONObject("politics"). There may be other mistakes in method names in my example.
the best solution to simplify your search and other operations on json object, is the convert json string to java object and doing your operations.
for convert json string to java object use follow code:
import org.codehaus.jackson.map.ObjectMapper;
import org.json.JSONException;
import org.json.JSONObject;
YourObject myObject;
ObjectMapper mapper = new ObjectMapper();
try{
myObject= mapper.readValue(jsonData, myObject.class);
}
catch (Exception e) {
e.printStackTrace();
}
for example define your class ass follow :
public class myObject{
private List<Politics> politics;
private Location location;
// define getters and setters
}
define Politics and Location class:
public class Politics
{
String type;
String friendly_type;
String name;
String code;
// define getters and setters
}
public class Location
{
String latitude;
String longitude;
// define getters and setters
}
It's because your are trying to get the inner element of the JSON Object.
try
JSONObject obj1 = new JSONObject(jsonobj);
JSONArray arr = (JSONArray) obj1.getObject("politics");
You will get a JSONArray object which further constitutes of JSON objects.
Now in order to get values using the key you must iterate array as given below:
for(int i=0; i<arr.size(); i++){
JSONObject obj = arr.getJSONArray(i);
System.out.println(obj.getString("type"));
}
which will now provide you with output:
admin2
admin6
constituency
admin6
admin4
constituency
I am creating JsonArray with the aid of jackson and I am trying to add a key map_data to the craeted JsonArray to send it as response to the Android app. How can I add it to the JsonArray?
I appreaciate any help.
{
"map_data":
[
{"route": 2, "latitude": 89.667781, "longitude": 13.517741},
{"route": 7, "latitude": 89.657772, "longitude": 13.537742},
{"route": 9, "latitude": 89.647763, "longitude": 13.547754},
{"route": 12, "latitude":89.637754, "longitude": 13.567765}
]
}
Code:
Database db = new Database();
List<MapData> lrl = db.get_map_data(selected);
try {
ObjectWriter ow = new ObjectMapper().writer()
.withDefaultPrettyPrinter();
String json = ow.writeValueAsString(lrl);
System.out.println("The output of json: " + json);
}
You can use ObjectWriter#withRootName(String) to give a root name
Method for constructing a new instance with configuration that
specifies what root name to use for "root element wrapping".
For example,
String json = ow.withRootName("map_data").writeValueAsString(lrl);
What you want as a result is a JSON object, containing a single field named map_data of type array. So that's what you should serialize instead of just serializing a list:
public class SomeClass {
#JsonProperty("map_data")
private List<MapData> mapData;
// getters and setters omitted for brevity
}
I'm a new Java programmer coming from a background in Python. I have weather data that's being collected/returned as a JSON with nested keys in it, and I don't understand how pull the values out in this situation. I'm sure this question has been asked before, but I swear I've Googled a great deal and I can't seem to find an answer. Right now I'm using json-simple, but I tried switching to Jackson and still couldn't figure out how to do this. Since Jackson/Gson seem to be the most used libraries, I'd would love to see an example using one of those libraries. Below is a sample of the data, followed by the code I've written so far.
{
"response": {
"features": {
"history": 1
}
},
"history": {
"date": {
"pretty": "April 13, 2010",
"year": "2010",
"mon": "04",
"mday": "13",
"hour": "12",
"min": "00",
"tzname": "America/Los_Angeles"
},
...
}
}
Main function
public class Tester {
public static void main(String args[]) throws MalformedURLException, IOException, ParseException {
WundergroundAPI wu = new WundergroundAPI("*******60fedd095");
JSONObject json = wu.historical("San_Francisco", "CA", "20100413");
System.out.println(json.toString());
System.out.println();
//This only returns 1 level. Further .get() calls throw an exception
System.out.println(json.get("history"));
}
}
The function 'historical' calls another function that returns a JSONObject
public static JSONObject readJsonFromUrl(URL url) throws MalformedURLException, IOException, ParseException {
InputStream inputStream = url.openStream();
try {
JSONParser parser = new JSONParser();
BufferedReader buffReader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
String jsonText = readAll(buffReader);
JSONObject json = (JSONObject) parser.parse(jsonText);
return json;
} finally {
inputStream.close();
}
}
With Jackson's tree model (JsonNode), you have both "literal" accessor methods ('get'), which returns null for missing value, and "safe" accessors ('path'), which allow you to traverse "missing" nodes. So, for example:
JsonNode root = mapper.readTree(inputSource);
int h = root.path("response").path("history").getValueAsInt();
which would return the value at given path, or, if path is missing, 0 (default value)
But more conveniently, you can just use JSON pointer expression:
int h = root.at("/response/history").getValueAsInt();
There are other ways too, and often it is more convenient to actually model your structure as Plain Old Java Object (POJO).
Your content could fit something like:
public class Wrapper {
public Response response;
}
public class Response {
public Map<String,Integer> features; // or maybe Map<String,Object>
public List<HistoryItem> history;
}
public class HistoryItem {
public MyDate date; // or just Map<String,String>
// ... and so forth
}
and if so, you would traverse resulting objects just like any Java objects.
Use Jsonpath
Integer h = JsonPath.parse(json).read("$.response.repository.history", Integer.class);
Check out Jackson's ObjectMapper. You can create a class to model your JSON then use ObjectMapper's readValue method to 'deserialize' your JSON String into an instance of your model class. And vice-versa.
Try jpath API. It's xpath equivalent for JSON Data. You can read data by providing the jpath which will traverse the JSON data and return the requested value.
This Java class is the implementation as well as it has example codes on how to call the APIs.
https://github.com/satyapaul/jpath/blob/master/JSONDataReader.java
Readme -
https://github.com/satyapaul/jpath/blob/master/README.md
Example:
JSON Data:
{
"data": [{
"id": "13652355666_10154605514815667",
"uid": "442637379090660",
"userName": "fanffair",
"userFullName": "fanffair",
"userAction": "recommends",
"pageid": "usatoday",
"fanPageName": "USA TODAY",
"description": "A missing Indonesian man was found inside a massive python on the island of Sulawesi, according to local authorities and news reports. ",
"catid": "NewsAndMedia",
"type": "link",
"name": "Indonesian man swallowed whole by python",
"picture": "https:\/\/external.xx.fbcdn.net\/safe_image.php?d=AQBQf3loH5-XP6hH&w=130&h=130&url=https%3A%2F%2Fwww.gannett-cdn.com%2F-mm-%2F1bb682d12cfc4d1c1423ac6202f4a4e2205298e7%2Fc%3D0-5-1821-1034%26r%3Dx633%26c%3D1200x630%2Flocal%2F-%2Fmedia%2F2017%2F03%2F29%2FUSATODAY%2FUSATODAY%2F636263764866290525-Screen-Shot-2017-03-29-at-9.27.47-AM.jpg&cfs=1&_nc_hash=AQDssV84Gt83dH2A",
"full_picture": "https:\/\/external.xx.fbcdn.net\/safe_image.php?d=AQBQf3loH5-XP6hH&w=130&h=130&url=https%3A%2F%2Fwww.gannett-cdn.com%2F-mm-%2F1bb682d12cfc4d1c1423ac6202f4a4e2205298e7%2Fc%3D0-5-1821-1034%26r%3Dx633%26c%3D1200x630%2Flocal%2F-%2Fmedia%2F2017%2F03%2F29%2FUSATODAY%2FUSATODAY%2F636263764866290525-Screen-Shot-2017-03-29-at-9.27.47-AM.jpg&cfs=1&_nc_hash=AQDssV84Gt83dH2A",
"message": "Akbar Salubiro was reported missing after he failed to return from harvesting palm oil.",
"link": "http:\/\/www.usatoday.com\/story\/news\/nation-now\/2017\/03\/29\/missing-indonesian-man-swallowed-whole-reticulated-python\/99771300\/",
"source": "",
"likes": {
"summary": {
"total_count": "500"
}
},
"comments": {
"summary": {
"total_count": "61"
}
},
"shares": {
"count": "4"
}
}]
}
Code snippet:
String jPath = "/data[Array][1]/likes[Object]/summary[Object]/total_count[String]";
String value = JSONDataReader.getStringValue(jPath, jsonData);
At the moment i'm trying to understand json and how it works.
But i have a problem with an array of objects.
all objects in the array have a key called "value" (i know it's weird, it's not my code) what also is an object.
And now to the problem: This object called "value" has always different key-values.
So i dont now how i can parse the json code to java object code, when it differ, every time.
Here some examples:
First object of the array:
"value":
{
"local":
[
"English", "Deutsch", Espanol"
],
"english":
[
"English", "Deutsch", Espanol"
],
},
Second object(now a string, not object) of the array:
"value" : "",
Third object of the array:
"value" : {},
...
Maybe I'm doing the parsing wrong.
First I have created the beans classes in java for the json code and then I'm using the automatic parser of google. (gson)
It works when only one of the examples above is inside the json code. (it should not differ, like changing from string to object...)
Gson gson = new Gson();
Output output = gson.fromJson(json, Output.class);
Output is the main class for the json stuff.
I have found out that maybe while parsing I could check a value called "id" first, and from that I could create another beans class with the right variables ...
Thats the code i need to parse to java objects and how do you do that??
The problem is the key called "value", because its always different.
With my method of using the google parser "gson" it wont work, because i'm getting exception that its an string but i was waiting for an object...
{
"status":"success",
"data":{
"panel":{
"title":{
"label":{ "local":"Tote Selection", "english":"Tote Selection" },
"image":"public/img/pick.jpg", "type":"default"
},
"isFirst":false, // currently not used
"isLast":false, // currently not used
"ownCount":0, // currently not used
"panelsCount":0, // currently not used
"elements":[
{
"type":"text",
"id":"1", "value":{ "local":"Scan next order tote",
"english":"Scan next order tote" },
"label":{ "local":"", "english":"" }, "color":"000000",
"fontsize":18, "fontstyle":"flat", "alignment":"left",
"rows":"undefined", "bgcolor":"", "isFocus":false
},
{
"type":"text",
"id":"4", "value":{ "local":"Scan tote: ", "english":"Scan tote: " },
"label":{ "local":"", "english":"" }, "color":"000000", "fontsize":20,
"fontstyle":"strong", "alignment":"left", "rows":"undefined",
"bgcolor":"", "isFocus":false
},
{
"type":"input",
"id":"6", "value":"", "label":{ "local":"", "english":"" },
"color":"000000", "fontsize":24, "fontstyle":"flat", "alignment":"left",
"rows":"undefined", "isFocus":true
},
{
"type":"button",
"id":"1", "value":{ "local":"", "english":"" },
"label":{ "local":"Menu", "english":"Menu" }, "color":"000000",
"fontsize":14, "fontstyle":"strong", "alignment":"left",
"rows":"undefined", "isFocus":false
},
{
"type":"button",
"id":"4", "value":{ "local":"", "english":"" },
"label":{ "local":"Enter", "english":"Enter" }, "color":"000000",
"fontsize":14, "fontstyle":"strong", "alignment":"right",18
"rows":"undefined", "isFocus":false
}
]
},
"authToken":"0fdd440a-619f-4936-ab74-d189accb5bd9",
"routing":{
"controller":"panel",
"action":"process",
"workflowId":"singlepicking",
"taskId":"orderSelection"
}
}
}
Thank you for your help!
it looks a little bit different but your answer helped me! Thx
JsonParser parser = new JsonParser();
JsonObject obj = parser.parse(br).getAsJsonObject();
//now getting all the json values
String status = obj.get("status").getAsString();
JsonObject data = obj.getAsJsonObject("data");
String authToken = data.get("authToken").getAsString();
JsonObject routing = data.getAsJsonObject("routing");
String controller = routing.get("controller").getAsString();
String action = routing.get("action").getAsString();
String workflowId = routing.get("taskId").getAsString();
If I understood ur question properly u can retrieve the values of the JSONArray as below
for (int i = 0; i < JArray.length(); i++) {
print(JArray.getJSONObject(i).tostring())
}
So if i am right u are getting the JSON from a String First?? so please try below first store the String in JSONObject as JSONObject obj = new JSONObject(str);//str is the string that u are getting
to get the valueenglish that are in data-panel-tittle-label is
String englishinLable=obj .getJSONObject("data").getJSONObject("panel").getJSONObject("title").getJSONObject("label").optString("english")