我有以下JSON文本。我如何解析它以获得pageName, pagePic, post_id等的值?

{
  "pageInfo": {
    "pageName": "abc",
    "pagePic": "http://example.com/content.jpg"
  },
  "posts": [
    {
      "post_id": "123456789012_123456789012",
      "actor_id": "1234567890",
      "picOfPersonWhoPosted": "http://example.com/photo.jpg",
      "nameOfPersonWhoPosted": "Jane Doe",
      "message": "Sounds cool. Can't wait to see it!",
      "likesCount": "2",
      "comments": [],
      "timeOfPost": "1234567890"
    }
  ]
}

当前回答

除了其他答案,我推荐这个在线开源服务jsonschema2pojo.org,它可以从json或json模式快速生成Java类,用于GSON, Jackson 1。或者Jackson 2.x。例如,如果你有:

{
   "pageInfo": {
         "pageName": "abc",
         "pagePic": "http://example.com/content.jpg"
    }
    "posts": [
         {
              "post_id": "123456789012_123456789012",
              "actor_id": 1234567890,
              "picOfPersonWhoPosted": "http://example.com/photo.jpg",
              "nameOfPersonWhoPosted": "Jane Doe",
              "message": "Sounds cool. Can't wait to see it!",
              "likesCount": 2,
              "comments": [],
              "timeOfPost": 1234567890
         }
    ]
}

GSON的jsonschema2pojo.org生成:

@Generated("org.jsonschema2pojo")
public class Container {
    @SerializedName("pageInfo")
    @Expose
    public PageInfo pageInfo;
    @SerializedName("posts")
    @Expose
    public List<Post> posts = new ArrayList<Post>();
}

@Generated("org.jsonschema2pojo")
public class PageInfo {
    @SerializedName("pageName")
    @Expose
    public String pageName;
    @SerializedName("pagePic")
    @Expose
    public String pagePic;
}

@Generated("org.jsonschema2pojo")
public class Post {
    @SerializedName("post_id")
    @Expose
    public String postId;
    @SerializedName("actor_id")
    @Expose
    public long actorId;
    @SerializedName("picOfPersonWhoPosted")
    @Expose
    public String picOfPersonWhoPosted;
    @SerializedName("nameOfPersonWhoPosted")
    @Expose
    public String nameOfPersonWhoPosted;
    @SerializedName("message")
    @Expose
    public String message;
    @SerializedName("likesCount")
    @Expose
    public long likesCount;
    @SerializedName("comments")
    @Expose
    public List<Object> comments = new ArrayList<Object>();
    @SerializedName("timeOfPost")
    @Expose
    public long timeOfPost;
}

其他回答

您可以使用DSM流解析库来解析复杂的json和XML文档。DSM只解析一次数据,不会将所有数据加载到内存中。

假设我们有一个Page类来反序列化给定的json数据。

页面类

public class Page {
    private String pageName;
    private String pageImage;
    private List<Sting> postIds;

    // getter/setter

}

创建一个yaml Mapping文件。

result:
  type: object     # result is array
  path: /posts
  fields:
    pageName:
        path: /pageInfo/pageName
    pageImage:
        path: /pageInfo/pagePic
    postIds:
      path: post_id
      type: array

使用DSM提取字段。

DSM dsm=new DSMBuilder(new File("path-to-yaml-config.yaml")).create(Page.class);
Page page= (Page)dsm.toObject(new path-to-json-data.json");

页面变量序列化为json:

{
  "pageName" : "abc",
  "pageImage" : "http://example.com/content.jpg",
  "postIds" : [ "123456789012_123456789012" ]
}

DSM非常适合处理复杂的json和xml。

由于还没有人提到它,这里是一个使用Nashorn (Java 8的JavaScript运行时部分,但在Java 11中已弃用)的解决方案的开始。

解决方案

private static final String EXTRACTOR_SCRIPT =
    "var fun = function(raw) { " +
    "var json = JSON.parse(raw); " +
    "return [json.pageInfo.pageName, json.pageInfo.pagePic, json.posts[0].post_id];};";

public void run() throws ScriptException, NoSuchMethodException {
    ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
    engine.eval(EXTRACTOR_SCRIPT);
    Invocable invocable = (Invocable) engine;
    JSObject result = (JSObject) invocable.invokeFunction("fun", JSON);
    result.values().forEach(e -> System.out.println(e));
}

性能比较

我编写的JSON内容包含三个数组,分别为20、20和100个元素。我只想从第三个数组中获取100个元素。我使用下面的JavaScript函数来解析和获取我的条目。

var fun = function(raw) {JSON.parse(raw).entries};

使用Nashorn运行一百万次调用需要7.5~7.8秒

(JSObject) invocable.invokeFunction("fun", json);

org。Json需要20~21秒

new JSONObject(JSON).getJSONArray("entries");

杰克逊用时6.5~7秒

mapper.readValue(JSON, Entries.class).getEntries();

在这种情况下,Jackson的性能比Nashorn好,后者的性能比org.json好得多。 Nashorn API比org更难使用。json或Jackson的。根据您的需求,Jackson和Nashorn都是可行的解决方案。

如果你的数据很简单,你不想要外部依赖,可以使用以下几行代码:

/**
 * A very simple JSON parser for one level, everything quoted.
 * @param json the json content.
 * @return a key => value map.
 */
public static Map<String, String> simpleParseJson(String json) {
    Map<String, String> map = new TreeMap<>();
    String qs[] = json.replace("\\\"", "\u0001").replace("\\\\", "\\").split("\"");
    for (int i = 1; i + 3 < qs.length; i += 4) {
        map.put(qs[i].replace('\u0001', '"'), qs[i + 2].replace('\u0001', '"'));
    }
    return map;
}

这些数据

{"name":"John", "age":"30", "car":"a \"quoted\" back\\slash car"}

生成一个包含

{age=30, car=a "quoted" back\slash car, name=John}

这也可以升级为使用未加引号的值…

/**
 * A very simple JSON parser for one level, names are quoted.
 * @param json the json content.
 * @return a key => value map.
 */
public static Map<String, String> simpleParseJson(String json) {
    Map<String, String> map = new TreeMap<>();
    String qs[] = json.replace("\\\"", "\u0001").replace("\\\\",  "\\").split("\"");
    for (int i = 1; i + 1 < qs.length; i += 4) {
        if (qs[i + 1].trim().length() > 1) {
            String x = qs[i + 1].trim();
            map.put(qs[i].replace('\u0001', '"'), x.substring(1, x.length() - 1).trim().replace('\u0001', '"'));
            i -= 2;
        } else {
            map.put(qs[i].replace('\u0001', '"'), qs[i + 2].replace('\u0001', '"'));
        }
    }
    return map;
}

为了解决复杂的结构,它变得很难看… ... 对不起! !... 但我忍不住把它编码了^^ 这将解析给定的JSON以及更多内容。它产生嵌套的映射和列表。

/**
 * A very simple JSON parser, names are quoted.
 * 
 * @param json the json content.
 * @return a key => value map.
 */
public static Map<String, Object> simpleParseJson(String json) {
    Map<String, Object> map = new TreeMap<>();
    String qs[] = json.replace("\\\"", "\u0001").replace("\\\\", "\\").split("\"");
    int index[] = { 1 };
    recurse(index, map, qs);
    return map;
}

/**
 * Eierlegende Wollmilchsau.
 * 
 * @param index index into array.
 * @param map   the current map to fill.
 * @param qs    the data.
 */
private static void recurse(int[] index, Map<String, Object> map, String[] qs) {
    int i = index[0];
    for (;; i += 4) {
        String end = qs[i - 1].trim(); // check for termination of an object
        if (end.startsWith("}")) {
            qs[i - 1] = end.substring(1).trim();
            i -= 4;
            break;
        }

        String key = qs[i].replace('\u0001', '"');
        String x = qs[i + 1].trim();
        if (x.endsWith("{")) {
            x = x.substring(0, x.length() - 1).trim();
            if (x.endsWith("[")) {
                List<Object> list = new ArrayList<>();
                index[0] = i + 2;
                for (;;) {
                    Map<String, Object> inner = new TreeMap<>();
                    list.add(inner);
                    recurse(index, inner, qs);
                    map.put(key, list);
                    i = index[0];

                    String y = qs[i + 3]; // check for termination of array
                    if (y.startsWith("]")) {
                        qs[i + 3] = y.substring(1).trim();
                        break;
                    }
                }
                continue;
            }

            Map<String, Object> inner = new TreeMap<>();
            index[0] = i + 2;
            recurse(index, inner, qs);
            map.put(key, inner);
            i = index[0];
            continue;
        }
        if (x.length() > 1) { // unquoted
            String value = x.substring(1, x.length() - 1).trim().replace('\u0001', '"');
            if ("[]".equals(value)) // handle empty array
                map.put(key, new ArrayList<>());
            else
                map.put(key, value);
            i -= 2;
        } else {
            map.put(key, qs[i + 2].replace('\u0001', '"'));
        }
    }
    index[0] = i;
}

yield -如果你打印地图:

{pageInfo={pageName=abc, pagePic=http://example.com/content.jpg}, posts=[{actor_id=1234567890, comments=[], likesCount=2, message=Sounds cool. Can't wait to see it!, nameOfPersonWhoPosted=Jane Doe, picOfPersonWhoPosted=http://example.com/photo.jpg, post_id=123456789012_123456789012, timeOfPost=1234567890}]}

主要有两种选择……

Object mapping. When you deserialize JSON data to a number of instances of: 1.1. Some predefined classes, like Maps. In this case, you don't have to design your own POJO classes. Some libraries: org.json.simple https://www.mkyong.com/java/json-simple-example-read-and-write-json/ 1.2. Your own POJO classes. You have to design your own POJO classes to present JSON data, but this may be helpful if you are going to use them into your business logic as well. Some libraries: Gson, Jackson (see http://tutorials.jenkov.com/java-json/index.html)

映射的主要缺点是它会导致大量内存分配(以及GC压力)和CPU占用。

面向流的解析。例如,Gson和Jackson都支持这种轻量级解析。另外,您还可以查看一个自定义的、快速的、无gc的解析器示例https://github.com/anatolygudkov/green-jelly。在需要解析大量数据和对延迟敏感的应用程序中,更倾向于使用这种方式。

{
   "pageInfo": {
         "pageName": "abc",
         "pagePic": "http://example.com/content.jpg"
    },
    "posts": [
         {
              "post_id": "123456789012_123456789012",
              "actor_id": "1234567890",
              "picOfPersonWhoPosted": "http://example.com/photo.jpg",
              "nameOfPersonWhoPosted": "Jane Doe",
              "message": "Sounds cool. Can't wait to see it!",
              "likesCount": "2",
              "comments": [],
              "timeOfPost": "1234567890"
         }
    ]
}

Java code :

JSONObject obj = new JSONObject(responsejsonobj);
String pageName = obj.getJSONObject("pageInfo").getString("pageName");

JSONArray arr = obj.getJSONArray("posts");
for (int i = 0; i < arr.length(); i++)
{
    String post_id = arr.getJSONObject(i).getString("post_id");
    ......etc
}