我有以下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"
    }
  ]
}

当前回答

可以使用Apache @Model注释创建表示JSON文件结构的Java模型类,并使用它们访问JSON树中的各种元素。与其他解决方案不同,该解决方案完全没有反射,因此适用于不可能反射或开销很大的环境。

有一个示例Maven项目展示了这种用法。首先它定义了结构:

@Model(className="RepositoryInfo", properties = {
    @Property(name = "id", type = int.class),
    @Property(name = "name", type = String.class),
    @Property(name = "owner", type = Owner.class),
    @Property(name = "private", type = boolean.class),
})
final class RepositoryCntrl {
    @Model(className = "Owner", properties = {
        @Property(name = "login", type = String.class)
    })
    static final class OwnerCntrl {
    }
}

然后它使用生成的RepositoryInfo和Owner类来解析所提供的输入流,并在此过程中获取某些信息:

List<RepositoryInfo> repositories = new ArrayList<>();
try (InputStream is = initializeStream(args)) {
    Models.parse(CONTEXT, RepositoryInfo.class, is, repositories);
}

System.err.println("there is " + repositories.size() + " repositories");
repositories.stream().filter((repo) -> repo != null).forEach((repo) -> {
    System.err.println("repository " + repo.getName() + 
        " is owned by " + repo.getOwner().getLogin()
    );
})

就是这样!除此之外,这里还有一个生动的要点,展示了类似的例子以及异步网络通信。

其他回答

您可以使用JsonNode来表示JSON字符串的结构化树。它是无处不在的杰克逊图书馆的一部分。

ObjectMapper mapper = new ObjectMapper();
JsonNode yourObj = mapper.readTree("{\"k\":\"v\"}");

您可以使用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。

本页的热门答案使用了太简单的例子,比如只有一个属性的对象(例如{name: value})。我认为这个简单但真实的例子可以帮助到一些人。

这是谷歌Translate API返回的JSON:

{
  "data": 
     {
        "translations": 
          [
            {
              "translatedText": "Arbeit"
             }
          ]
     }
}

我想检索“translatedText”属性的值。“Arbeit”使用谷歌的Gson。

两种可能的方法:

Retrieve just one needed attribute String json = callToTranslateApi("work", "de"); JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject(); return jsonObject.get("data").getAsJsonObject() .get("translations").getAsJsonArray() .get(0).getAsJsonObject() .get("translatedText").getAsString(); Create Java object from JSON class ApiResponse { Data data; class Data { Translation[] translations; class Translation { String translatedText; } } } ... Gson g = new Gson(); String json =callToTranslateApi("work", "de"); ApiResponse response = g.fromJson(json, ApiResponse.class); return response.data.translations[0].translatedText;

org。Json库易于使用。

只要记住(在强制转换或使用getJSONObject和getJSONArray等方法时)JSON表示法

[…]表示一个数组,因此库将把它解析为JSONArray {…}表示一个对象,因此库将把它解析为JSONObject

示例代码如下:

import org.json.*;

String jsonString = ... ; //assign your JSON String here
JSONObject obj = new JSONObject(jsonString);
String pageName = obj.getJSONObject("pageInfo").getString("pageName");

JSONArray arr = obj.getJSONArray("posts"); // notice that `"posts": [...]`
for (int i = 0; i < arr.length(); i++)
{
    String post_id = arr.getJSONObject(i).getString("post_id");
    ......
}

你可以从以下几个方面找到更多的例子

可下载的jar: http://mvnrepository.com/artifact/org.json/json

由于还没有人提到它,这里是一个使用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都是可行的解决方案。