Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Output list of all paths to leaf nodes in a json document in java

For example: Given this json document:

{
    "store": {
        "book": [
            {
                "category": "reference",
                "author": "Nigel Rees",
                "title": "Sayings of the Century",
                "price": 8.95
            },
            {
                "category": "fiction",
                "author": "Herman Melville",
                "title": "Moby Dick",
                "isbn": "0-553-21311-3",
                "price": 8.99
            },
        ],
        "bicycle": {
            "color": "red",
            "price": 19.95
        }
    },
    "expensive": 10
}

I would like to produce (something like) this output:

store.book.category: "reference"
store.book.author: "Nigel Rees"
store.book.title: "Sayings of the Century"
store.book.price: 8.95
store.book.category: "fiction"
store.book.author: "Herman Melville"
store.book.title: "Moby Dick"
store.book.isbn: "0-553-21311-3"
store.book.price: 8.99
store.bicycle.color: "red"
store.bicycle.price: 19.95
expensive:10

Rather than work from raw text, I would prefer an efficient solution based on one of the robust json libraries (gson, jackson, etc.).

like image 442
L. Blanc Avatar asked Oct 03 '14 17:10

L. Blanc


2 Answers

Here is a sample code with org.json. But the same can be used with Gson/Jackson with changes to appropriate types within those libraries. You could also using StringBuilder instead of String for the keys here.

import java.util.Iterator;
import org.json.JSONArray;
import org.json.JSONObject;

public class MyJSONTest {

  private static void listJson(JSONObject json) {
    listJSONObject("", json);
  }

  private static void listObject(String parent, Object data) {
    if (data instanceof JSONObject) {
      listJSONObject(parent, (JSONObject)data);
    } else if (data instanceof JSONArray) {
      listJSONArray(parent, (JSONArray) data);
    } else {
      listPrimitive(parent, data);
    }    
  }

  private static void listJSONObject(String parent, JSONObject json) {
    Iterator it = json.keys();
    while (it.hasNext()) {
      String key = (String)it.next();
      Object child = json.get(key);
      String childKey = parent.isEmpty() ? key : parent + "." + key;
      listObject(childKey, child);
    }
  }

  private static void listJSONArray(String parent, JSONArray json) {
    for (int i = 0; i < json.length(); i++) {
      Object data = json.get(i);
      listObject(parent + "[" + i + "]", data);
    }
  }

  private static void listPrimitive(String parent, Object obj) {
    System.out.println(parent + ":"  + obj);
  }

  public static void main(String[] args) {
    String data = "{\"store\":{\"book\":[{\"category\":\"reference\",\"author\":\"NigelRees\",\"title\":\"SayingsoftheCentury\",\"price\":8.95},{\"category\":\"fiction\",\"author\":\"HermanMelville\",\"title\":\"MobyDick\",\"isbn\":\"0-553-21311-3\",\"price\":8.99},],\"bicycle\":{\"color\":\"red\",\"price\":19.95}},\"expensive\":10}";
    JSONObject json = new JSONObject(data);    
    System.out.println(json.toString(2));
    listJson(json);
  }

}
like image 164
Neo Avatar answered Nov 08 '22 19:11

Neo


Turns out this is pretty easy to do using Gson, especially with the JsonReader.getPath() method introduced in 2.3.

static void parseJson(String json) throws IOException {

    JsonReader reader = new JsonReader(new StringReader(json));
    reader.setLenient(true);
    while (true) {
        JsonToken token = reader.peek();
        switch (token) {
            case BEGIN_ARRAY:
                reader.beginArray();
                break;
            case END_ARRAY:
                reader.endArray();
                break;
            case BEGIN_OBJECT:
                reader.beginObject();
                break;
            case END_OBJECT:
                reader.endObject();
                break;
            case NAME:
                reader.nextName();
                break;
            case STRING:
                String s = reader.nextString();
                print(reader.getPath(), quote(s));
                break;
            case NUMBER:
                String n = reader.nextString();
                print(reader.getPath(), n);
                break;
            case BOOLEAN:
                boolean b = reader.nextBoolean();
                print(reader.getPath(), b);
                break;
            case NULL:
                reader.nextNull();
                break;
            case END_DOCUMENT:
                return;
        }
    }
}

static private void print(String path, Object value) {
    path = path.substring(2);
    path = PATTERN.matcher(path).replaceAll("");
    System.out.println(path + ": " + value);
}

static private String quote(String s) {
    return new StringBuilder()
            .append('"')
            .append(s)
            .append('"')
            .toString();
}

static final String REGEX = "\\[[0-9]+\\]";
static final Pattern PATTERN = Pattern.compile(REGEX);
like image 32
L. Blanc Avatar answered Nov 08 '22 20:11

L. Blanc