1

I am trying to get a json(has unknown template) value with a dynamic key like;

"user.specs.id"

Problem is my json structure is not static and because of this I can't parse it to a java Object or get its properties with Gson methods.

{
    "user": {
        "specs": {
            "id": 12222,
            "name": "foo"
        } 
    }
}

Is there a way to extract some data from any json with some key?

EDIT: I have a service method like;

public Object getValueByKey(String json, String key);

possible values for "json" param;

{"name": "test"}    //possible key "name"

{"user": {"id": 1232}}   //possible key "user.id"

{"cars": ["car1", "car2"]}   //possible key "cars[0]"
hellzone
  • 5,393
  • 25
  • 82
  • 148
  • Does this answer your question? [How to parse a dynamic JSON key in a Nested JSON result?](https://stackoverflow.com/questions/7304002/how-to-parse-a-dynamic-json-key-in-a-nested-json-result) – Guy Nov 27 '19 at 08:30
  • There are several libraries designed to parse JSON without a fixed data model, e.g. [GSON](https://github.com/google/gson) – T A Nov 27 '19 at 08:37
  • I hope you can use https://github.com/mikolajmitura/java-properties-to-json – Araf Nov 27 '19 at 08:38
  • @Guy No its not. I am not looking for a single key like "user" but a multiple combined key like "user.specs.id" – hellzone Nov 27 '19 at 08:42
  • 3
    You can use `JsonPath` library. `Jackson` allows similar solution with `JsonPointer`. See related questions: [Parsing deeply nested JSON properties with Jackson](https://stackoverflow.com/questions/57978790/parsing-deeply-nested-json-properties-with-jackson), [Iterate over a large JSON Array with JSONPath](https://stackoverflow.com/questions/55366515/iterate-over-a-large-json-array-with-jsonpath), [how to parse a huge JSON file without loading it in memory](https://stackoverflow.com/questions/54817985/how-to-parse-a-huge-json-file-without-loading-it-in-memory/54818259#54818259) – Michał Ziober Nov 27 '19 at 08:43
  • @MichałZiober My JSON template is not static. Think that user is importing his own json data/template to my service.So I can't convert it to some java object – hellzone Nov 27 '19 at 08:46
  • @hellzone, but how do you know where to search for `id`? Also, `JsonPath` and `Jackson` don't force you to deserialise `JSON` to `POJO` class. You can deserialise `JSON` to `JsonNode` which represents tree structure of given `JSON` payload. Take a look on linked questions and you will see that this feature allows to read given value without deserialisation to class. – Michał Ziober Nov 27 '19 at 08:50
  • @MichałZiober " but how do you know where to search for id". I have a complete property path like "user.specs.id". It means look for "user" key at parent directory then look for "specs" key and inside it look for "id" key and get its value. Check my edit. You can't write this service method with your answer. – hellzone Nov 27 '19 at 09:01

1 Answers1

2

As @Michał Ziober's comment, you can simply achieve this by using JsonPath as follows:

Maven dependency

<dependency>
    <groupId>com.jayway.jsonpath</groupId>
    <artifactId>json-path</artifactId>
    <version>2.4.0</version>
</dependency>

Code snippet

public static void main(String[] args) {
    getValueByKey("{\"name\": \"test\"}", "name");
    getValueByKey("{\"user\": {\"id\": 1232}}", "user.id");
    getValueByKey("{\"cars\": [\"car1\", \"car2\"]}", "cars[0]");
}

public static void getValueByKey(String json, String key) {
    DocumentContext jsonContext = JsonPath.parse(json);
    Object value = jsonContext.read(key);
    System.out.println(value.toString());
}

Console output

11:38:50.840 [main] DEBUG c.j.j.internal.path.CompiledPath - Evaluating path: $['name']
test
11:38:50.855 [main] DEBUG c.j.j.internal.path.CompiledPath - Evaluating path: $['user']['id']
1232
11:38:50.855 [main] DEBUG c.j.j.internal.path.CompiledPath - Evaluating path: $['cars'][0]
car1


Read more

LHCHIN
  • 3,679
  • 2
  • 16
  • 34