Selecting a subset of JSON properties and values using JSONPath - java

Given a JSON like:
{
"a":1,
"b":2,
"c":3,
"d":4,
"e":5
}
How can I select out b, d and e to get the following JSON?
{
"b":2,
"d":4,
"e":5
}
I want a JSON object and NOT only 2, 4 and 5 values?
This is what I'm trying with and failing:
$.[b,d,e]

JSONPath is not suitable for what you are trying to achieve: JSONPath is designed to select values and not key-value pairs. What you want could be achieved with Jackson or any JSON parser for Java.
If you want to go for Jackson here's the code that will do the trick:
String json = "{\"a\":1,\"b\":2,\"c\":3,\"d\":4,\"e\":5}";
ObjectMapper mapper = new ObjectMapper();
JsonNode tree = mapper.readTree(json);
ObjectNode node = mapper.createObjectNode();
node.set("b", tree.get("b"));
node.set("d", tree.get("d"));
node.set("e", tree.get("e"));
String result = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(node);

Elements must be in single quotes.
$.['b','d','e']
Works fine for JsonPath from com.jayway.jsonpath:json-path:2.4.0

Your json path is correct, while json it self is not. It should be:
{
"a":1,
"b":2,
"c":3,
"d":4,
"e":5
}
BTW there is good online testing resources for these purposes: http://jsonpath.com/

You need to modify your JSON to (as said by Andremoniy)
{
"a":1,
"b":2,
"c":3,
"d":4,
"e":5
}
and to select b,d,e use this
$.b,d,e

Related

Unknown depth nested maps check key existence and get value

I have a hashmap of the following structure:-
mymap = {a:{b:{c:{d:{e}}}}
How do I check the existance of key "d" in hashmap mymap in the simplest way?
Is there any Java8 features that might come in handy here?
mymap.get( "a" )).get( "b" )..;
is not going to work because I don't know the level in which d is nested.
How do I check if d is present in the map, and get its value without this trailing call? Thanks in advance.
I have recently had a similar problem and managed to come up with a solution which works with any JSON depths.
It is a solution which transforms the String into a JsonNode Object and then tries to find the parent value of a given fieldName (in this case 'd'). The result returning something which is not null, will tell you if the value exists or not.
ObjectMapper mapper = new ObjectMapper();
String myMapJson = "{\"a\":{\"b\":{\"c\":{\"d\":{\"e\":\"\"}}}}"
JsonNode data = mapper.readTree(myMapJson);
if (((ObjectNode)data.findParent("d")) != null) {
// Do something if value is found
} else {
// Do something if value is not found
}
Hope this helps..
You can use the FasterXML-Jackson library, which gives you the simplicty of traversing over nesed json.
For example:
ObjectMapper mapper = new ObjectMapper(); // can reuse, share globally
String myMapJson = "{\"a\":{\"b\":{\"c\":{\"d\":{\"e\":\"\"}}}}"
JsonNode data = mapper.readTree(myMapJson);
boolean hasKey = data.has("d");
Or, if you already have the object as Map you can write it as json and then load it the same way above:
ObjectMapper mapper = new ObjectMapper(); // can reuse, share globally
String jsonData = mapper.writeValueAsString(myMapObject);
JsonNode data = mapper.readTree(jsonData);
boolean hasKey = data.has("d");
if (hasKey) {
JsonNode result = data.findValue("d");
}

Gson - Merge multiple JSONs objects into one JSON

I have a case where I need to merge multiple JSONs objects into one JSON.
A single response looks like this:
{"name":"MyName"}
Multiple merged JSON looks like this:
["{\"name\":\"name\"}","{\"name\":\"MyName\"}"]
The problem here is that the child JSONs that I want to include can come either from a Java object or are available as String itself.
MyRequest request = new MyRequest();
request.setName("name");
String singleJson = new Gson().toJson(request);
String fromSomePlaceElse = "{\"name\":\"MyName\"}";;
List<String> list = Lists.newArrayList(singleJson,fromSomePlaceElse);
System.out.println(new Gson().toJson(list));
The above gives me the following output:
["{\"name\":\"name\"}","{\"name\":\"MyName\"}"]
instead of:
[{"name":"MyName"}, {"name":"MyName"}]
I don't want to parse the already existing JSON and do the following:
List<MyRequest> list2 = Lists.newArrayList(request, new Gson().fromJson(fromSomePlaceElse, MyRequest.class));
System.out.println(new Gson().toJson(list2));
Can this be done using Gson ?
Just print it.
List<String> list = Lists.newArrayList(singleJson,fromSomePlaceElse);
System.out.println(list);
Then you can get
[{"name":"name"}, {"name":"MyName"}]
if you want json in form of string,you can directly use ---
new Gson().toJson(yourList, new TypeToken<List<JsonObject>>(){}.getType())
Try the given library to merge any amount of JSON-objects at once. The result can be returned as String or JsonObject (GSON). Please reference the code in this answer.

Using group-by type of operation on JSON objects

I have JSON data in the following format.
[{
"id": 16966,
"post": "This is about road!",
"category": "road",
},
.
.
.]
I want to group JSON entries according to their categories. So, I will get all road related entries in one datastructure, (say list). I know that I can put the data into Mongo DB or even a relational database and do querying. Without doing that, is there some easy method to do this?
If you gonna read the entire JSON file, an easy way is to first read all the entries into a List<Data> and then group them in a Map<String, List<Data>>.
class Data {
private int id;
private String post;
private String category;
//getter, equals, hashcode, toString, etc.
}
and then:
public class Test {
public static void main(String args[] ) throws Exception {
Gson gson = new Gson();
List<Data> list = gson.fromJson(new BufferedReader(new FileReader("myJson.json")), new TypeToken<List<Data>>(){}.getType());
Map<String, List<Data>> groupedMap = list.stream().collect(Collectors.groupingBy(Data::getCategory));
groupedMap.forEach((k, v) -> System.out.println(k + " => " + v));
}
}
which outputs:
road => [Data [id=16966, post=This is about road!, category=road], Data [id=16965, post=This is about road!, category=road]]
land => [Data [id=16961, post=This is about land!, category=land]]
I added some entries to the file. I guess you could write your own deserializer too to get rid of the step when you have a temporary list and store directly in the map, but you asked for an easy way :-). Also note that I'm using java-8 and Gson, but you can also achieve this without it (but you'll write more code).
Take a look on JXPath. This library allows running XPath queries on collections of java objects. So, you can map JSON to your java model using one of popular JSON parser (e.g. Jackson or Gson) and then JXPath to run XPath queries on your collection.
For more information refer here: http://commons.apache.org/proper/commons-jxpath/

how to parse multiple json objects with no name

im having some trouble parsing json. I have json in the format of:
{"blah":"blah","blah":"blah"}
{"blah":"blah","blah":"blah"}
{"blah":"blah","blah":"blah"}
Here is the link to the JSON: http://gerrit.aokp.co/query?format=JSON&q=status:merged&age:1d
I cant make this a jsonobject and iterate over it. I currently have it as a string.
Is there a way to iterate over this? there will be over 500.
I tried making it an array by adding square brackets around it, but it didnt work because i needed to divide them with commas. I cant manipulate this by hand because im getting it from the web. So i tried this.
jsonString = jsonString.replaceAll("}(?!,)", "},");
the reason im adding the negative comma is that sometimes i might have a jsonobject inside of of these objects so I only want to add a comma in front of the '}' without commas.
when i do the replaceall i get this error.
Error in fetching or parsing JSON: java.util.regex.PatternSyntaxException: Syntax error in regexp pattern near index 1:
}(?!,)
^
What am I doing wrong or is there an easier way to do this that im looking over?
EDIT:
Oh yes, I need to implement this in java because this is in an android app.
here is an example how you can accomplish what you want using Jackson's ObjectMapper.
ObjectMapper om = new ObjectMapper();
try {
List<Object> obj = om.readValue(yourJsonString, new TypeReference<List<Object>> () { });
} catch (IOException e1) {
e1.printStackTrace();
}
Now you will have a list of each of the individual Objects in your JSON string. To take it a step further you could create a POJO for the Object you are parsing.
Something like:
public class MyObject{
private String project;
private String branch;
}
That is just an exmple, you would need to define a property for each json property.
Then you can turn :
List<Object> obj = om.readValue(yourJsonString, new TypeReference<List<Object>> () { });
Into
List<MyObject> obj = om.readValue(yourJsonString, new TypeReference<List<MyObject>> () { });
Hope this helps!
From the link you posted, it looks like there are newlines between objects (and only between objects). If that's right, I'd approach it like this:
String[] items = dataFromWeb.split("\n");
String asJSONArrayString = Arrays.toString(items);
JSONArray jsonArray = new JSONArray(asJSONArrayString);
This splits the data at newlines, then joins it together with commas between elements and brackets around the whole thing.
JSONObject jObject = null;
mJsonString = downloadFileFromInternet(urlString);
jObject = new JSONObject(mJsonString);
This will get you json object.
This is the way to get json array from json object:
JSONArray jsonImageArray = jObject.getJSONArray("your string");

How can i sort Nested JSON Array?

How can i sort Nested JSON Array? Like for a JSON below...
{
"id":"rtmc05.lax.someabc.net",
"name":"rtmc05.lax.someabc.net",
"tenants":[{
"id":"rtmc",
"name":"rtmc"
},{
"id":"hrs",
"name":"hrs"
},{
"id":"amotelbe1",
"name":"amotelbe"
},{
"id":"cds",
"name":"cds"
},{
"id":"idx-server",
"name":"idx-server",
"tenants":[{
"id":"amotelbe",
"name":"amotelbe",
"tenants":[{
"id":"amotelui",
"name":"amotelui"
}]
}]
}]
}
There's a few parts implicit to your question, and it's not clear where you're having trouble:
How do you take a JSON string and make usable Java objects out of it. (I'm assuming Java, not JavaScript, since you've tagged your question with "java".)
How do you sort those objects after they're made?
How do you handle sorting the nested parts? (In your example, "idx-server" has sub-tenants.)
Not sure exactly which parts of this you're having trouble with, so here's some notes for all three.
Part 1: Getting Java objects
I agree with the other guy that Jackson is a good JSON parser to use. Here's a couple lines of code you could use to parse some JSON:
String jsonString = "..."; // Load this in whatever way makes sense for you
ObjectMapper mapper = new ObjectMapper();
Map<String,Object> parsedJson = mapper.readValue(jsonString, Map.class);
If your JSON string is really huge, then there are other readValue overloads that you can use to avoid reading the whole String into memory.
Part 2: Sorting Java objects
Once you've got the parsed JSON, sorting is just a matter of calling Collections.sort(...), passing in the tenants array. Plus you'll need to write a Comparator that defines the ordering that you want. For example, here's a comparator that sorts by name:
public class NameComparator implements Comparator<Map<String,Object>> {
public int compare(Map<String,Object> o1, Map<String,Object> o2) {
String name1 = (String) o1.get("name");
String name2 = (String) o2.get("name");
return name1.compareTo(name2);
}
}
Then you get the tenants array out (Jackson makes them into ArrayList objects) and call Collections.sort(...). For example,
List<Map<String,Object>> tenants =
(List<Map<String,Object>>) parsedJson.get("tenants");
Collections.sort(tenants, new NameComparator());
Part 3: Handling the nesting
The clearest way to do this is to add some extra code to walk through your JSON looking for any object with a tenants array, and sort it. For example, here's a recursive function that should do it:
public static void recursiveSortTenants(Map<String,Object> jsonObject) {
List<Map<String,Object>> tenants =
(List<Map<String,Object>>) jsonObject.get("tenants");
if (tenants != null) {
Collections.sort(tenants, new NameComparator());
// For each tenant, see if it has sub-tenants. If so,
// call this function again to sort them.
for (Map<String,Object> tenant : tenants) {
if (tenants.containsKey("tenants")) {
recursiveSortTenants(tenant);
}
}
}
}
Hope this helps!
Parse it into (javascript) objects then write a sort function that sorts an array of such javascript objects.
Deserialize it to POJOs(with Gson or Jackson), and write a Comparator for that POJOs.

Categories

Resources