Pamput
Pamput

Reputation: 2864

Query a JSONObject in java

I was wondering if somewhere out there exists a java library able to query a JSONObject. In more depth I'm looking for something like:

String json = "{ data: { data2 : { value : 'hello'}}}";

...
// Somehow we managed to convert json to jsonObject
...

String result = jsonObject.getAsString("data.data2.value");

System.out.println(result);

I expect to get "hello" as output.

So far, the fastest way I have found is using Gson:

jsonObject.getAsJsonObject("data").getAsJsonObject().get("data2").getAsJsonObject("value").getAsString();

It's not actually easy to write and read. Is there something faster?

Upvotes: 50

Views: 72530

Answers (7)

PeterH
PeterH

Reputation: 61

Another solution that works also with the current Java version (21) and also offers validation functionality is the Burningwave JSON library:

String json = "{ data: { data2 : { value : 'hello'}}}";
Facade facade = Facade.create(new ObjectMapper());
ObjectHandler jsonObjectHandler = facade.newObjectHandler(json , Map.class);
String value = jsonObjectHandler.newValueFinder().findFirstForPathEndsWith("value");

Upvotes: 3

Cromax
Cromax

Reputation: 2052

Using Java JSON API 1.1.x (javax.json) one can make use of new JavaPointer interface. Instance implementing this interface can be considered to some extend as kind of XPath expression analog (see RFC-6901 for details). So in your case you could write this:

import javax.json.*;
//...
var jp = Json.createPointer("/data/data2/value");
System.out.println(jp.getValue(jsonObject));

In 1.1.4 version of JSON there's also nice addition to JsonStructure interface (which is implemented by JsonObject and JsonArray), namely getValue(String jsonPointer). So it all comes down to this simple one-liner:

System.out.println(jsonObject.getValue("/data/data2/value"));

Upvotes: 1

GSK
GSK

Reputation: 71

You can use org.json

    String json = "{ data: { data2 : { value : 'hello'}}}";
    org.json.JSONObject obj = new org.json.JSONObject(json);
    System.out.println(obj.query("/data/data2/value"));

Upvotes: 7

Parvathy
Parvathy

Reputation: 2455

I think no way.

Consider a java class

class Student {
    Subject subject = new Subject();
}

class Subject {
    String name;
}

Here if we want to access subject name then

Student stud = new Student();
stud.subject.name; 

We cant access name directly, if so then we will not get correct subject name. Like here:

jsonObject.getAsJsonObject("data")
          .getAsJsonObject()
          .get("data2")
          .getAsJsonObject("value")
          .getAsString();

If you want to use same like java object then use

ClassName classObject = new Gson().fromJson(JsonString, ClassName.class);

ClassName must have all fields to match jsonstring. If you have a jsonobject inside a jsonobject then you have to create separate class like I'm doing in Student and Subject class.

Upvotes: 1

n1ckolas
n1ckolas

Reputation: 4450

I've just unexpectedly found very interesting project: JSON Path

JsonPath is to JSON what XPATH is to XML, a simple way to extract parts of a given document.

With this library you can do what you are requesting even easier, then my previous suggestion:

String hello = JsonPath.read(json, "$.data.data2.value");

System.out.println(hello); //prints hello

Hope this might be helpful either.

Upvotes: 49

StaxMan
StaxMan

Reputation: 116572

While not exactly the same, Jackson has Tree Model representation similar to Gson:

JsonNode root = objectMapper.readTree(jsonInput);
return root.get("data").get("data2").get("value").asText();

so you need to traverse it step by step.

EDIT (August 2015)

There actually is now (since Jackson 2.3) support for JSON Pointer expressions with Jackson. So you could alternatively use:

return root.at("/data/data2/value").asText();

Upvotes: 31

n1ckolas
n1ckolas

Reputation: 4450

First of all, I would recommend consider JSON object binding.

But in case if you get arbitrary JSON objects and you would like process them in the way you described, I would suggest combine Jackson JSON processor along with Apache's Commons Beanutils.

The idea is the following: Jackson by default process all JSON's as java.util.Map instances, meanwhile Commons Beanutils simplifies property access for objects, including arrays and Map supports.

So you may use it something like this:

//actually it is a Map instance with maps-fields within
Object jsonObj = objectMapper.readValue(json, Object.class);

Object hello = PropertyUtils.getProperty(jsonObj, "data.data2.value")

System.out.println(hello); //prints hello

Upvotes: 17

Related Questions