0

I'm trying to read contents of JSON arary in Java, and get each element as a JSON string. My attempts have failed.

Let's assume here is the base JSON:

{ "book": [ 
      { "category": "",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
        "price": ""
      },
      { "category": "fiction",
        "author": "",
        "title": "Sword of Honour",
        "price": "12.99"
      },
      { "category": "fiction",
        "author": "Herman Melville",
        "title": "Moby Dick",
        "isbn": "0-553-21311-3",
        "price": "8.99"
      },
      { "category": "fiction",
        "author": "J. R. R. Tolkien",
        "title": "The Lord of the Rings",
        "isbn": "0-395-19395-8",
        "price": 22.99
      }
    ]
}

And I iterate through the whole array, and need to get each element as JSON String (some properties can be empty). So first String would be:

{       "category": "",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
        "price": ""
}

What I did is this:

String response = Unirest.get(db).header("cache-control", "no-cache").asString().getBody();

            int length = JsonPath.read(response, "$.book.length()");
            System.out.println(length);
            for (int i = 0; i < length; i++) {
                String json = JsonPath.read(response, "$.book["+i+"]").toString();

                System.out.println("1111111\n"+json);

                process(json);
            }

But what I get is messy, and not the same string. It doesn't include "".

What is the solution?

7
  • 1
    Have you tried this? -> stackoverflow.com/questions/1568762/… Commented Feb 21, 2019 at 17:21
  • well, that's not JSONPath. Prefer not to change library at this time. Commented Feb 21, 2019 at 17:25
  • Hi there, you should provide some more context, there is a zillion different ways of reading a Json, so, please first start by showing us which library are you using (JsonPath ?) and what are you getting as a result (what is that you are calling messy). That will help us to identify your problem and help you better. fyi, I've never used this JsonPath before... Commented Feb 21, 2019 at 17:30
  • 1
    JSONPath was intuitve, so I used it so far. Well, the one @MiguelCruz suggested works, so no bother using JSONPath anymore! Commented Feb 21, 2019 at 17:41
  • I just tested your code here and it does work as "expected". You are using a library that reads a json thus it will response a json like object therefore no need for the double quotes in the values. For instance if you add in your code String json = JsonPath.read(response, "$.book["+i+"].category").toString() it will print blank for the first one and fiction for all others... If you want it to actually print it as a new json object you need to provide a specific Configuration for your read method. Just learned about it reading the docs :) Commented Feb 21, 2019 at 17:53

1 Answer 1

2

As I mentioned in comments JsonPath will read a JSON object and return it like so. It will be like a HashMap with the types being defined by what was parsed. If you, as you mentioned, wants the values as a Json after extracting it you need to convert what was read back to a Json again:

public static void main(String[] args) {
    String response = "{ \"book\": [ " + 
            "      { \"category\": \"\"," + 
            "        \"author\": \"Nigel Rees\"," + 
            "        \"title\": \"Sayings of the Century\"," + 
            "        \"price\": \"\"" + 
            "      }," + 
            "      { \"category\": \"fiction\"," + 
            "        \"author\": \"\"," + 
            "        \"title\": \"Sword of Honour\"," + 
            "        \"price\": \"12.99\"" + 
            "      }," + 
            "      { \"category\": \"fiction\"," + 
            "        \"author\": \"Herman Melville\"," + 
            "        \"title\": \"Moby Dick\"," + 
            "        \"isbn\": \"0-553-21311-3\"," + 
            "        \"price\": \"8.99\"" + 
            "      }," + 
            "      { \"category\": \"fiction\"," + 
            "        \"author\": \"J. R. R. Tolkien\"," + 
            "        \"title\": \"The Lord of the Rings\"," + 
            "        \"isbn\": \"0-395-19395-8\"," + 
            "        \"price\": 22.99" + 
            "      }" + 
            "    ]" + 
            "}";
    int length = JsonPath.read(response, "$.book.length()");
    System.out.println(length);
    Configuration conf = Configuration.defaultConfiguration();

    Object document = Configuration.defaultConfiguration().jsonProvider().parse(response);

    for (int i = 0; i < length; i++) {
        String json = conf.jsonProvider().toJson(JsonPath.read(document, "$.book["+i+"]"));
        System.out.println(json);
        //process(json);
    }
}

This will output:

{"category":"","author":"Nigel Rees","title":"Sayings of the Century","price":""}
{"category":"fiction","author":"","title":"Sword of Honour","price":"12.99"}
{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":"8.99"}
{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}

I just learned about it in the Docs, using the Configuration to parse the json will make your code parse it just once. It could even be improved (to remove the int length stuff), but I will leave it up to you :)

Sign up to request clarification or add additional context in comments.

5 Comments

Interesting! Yeah good solution. Although I already used the org.json library.
No problem. The good thing about it was that I get to learn something new cheers :)
And as a side note, I really liked the way JsonPath handles it and provides ways to do predicates, groupings and stuff, its like Mongo in java code... I will do some performance tests on it and if it is good enough start using it from now on.
Yeah it's great for finding specific value inside a JSON. I wonder why they didn't consider $.book[i] returning an item's JSON!
My best bet is that it was due to performance reasons... in order to understand the json you need to parse it into something (in their case mapping structure), therefore transform it into something else... in order to return an original portion of the json you have to convert it back so maybe would be easier to add a toJson method into the JsonPath class itself and therefore callable from read method as in ...read(...).toJson()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.