Java Gson、JSON 和 LinkedTreeMap 的微妙之处

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22285661/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 14:44:54  来源:igfitidea点击:

Gson, JSON and the subtleties of LinkedTreeMap

javajsongson

提问by ViRALiC

I've recently started playing around with JSONstrings, and was told that Google's own library, Gson, is the new and hip way of dealing with these.

我最近开始玩弄JSON字符串,并被告知 Google 自己的库Gson是处理这些字符串的新方法。

The way I've understood it, is that a JSONstring is essentially a map. Where each variable points to a value in the string.

我所理解的方式是,JSON字符串本质上是一张地图。其中每个变量指向字符串中的一个值。

For example:

例如:

String jsonInput2 = "{\"created_at\":\"Sat Feb 08 15:37:37 +0000 2014\",\"id\":432176397474623489\"}

Thus far, all is well. Information such as when this JSONstring was created, can be assigned to a variable with the following code:

到目前为止,一切都很好。JSON可以使用以下代码将诸如创建此字符串的时间之类的信息分配给变量:

Gson gson = new Gson();

Map<String, String> map = new HashMap<String, String>();

map = (Map<String, String>) gson.fromJson(jsonInput, map.getClass());

String createdAt = map.get("created_at");

It's almost artistic in in simple beauty. But this is where the beauty ends and my confusion begins.

它在简单的美中几乎是艺术的。但这就是美丽结束的地方,我的困惑开始了。

The following is an extension of the above JSONstring;

以下是上述JSON字符串的扩展;

String jsonInput2 = "{\"created_at\":\"Sat Feb 08 15:37:37 +0000 2014\",\"id\":432176397474623489\",\"user\":{\"id_str\":\"366301747\",\"name\":\"somethingClever\",\"screen_name\":\"somethingCoolAndClever\"}}";

My question is how these "brackets within brackets" work for the usersection of the JSON?

我的问题是如何将这些工作“中括号括号”,为user的部分JSON

How could I assign the values specified within these inner-brackets to variables?

如何将这些内括号中指定的值分配给变量?

Can anyone explain to me, or show me in code, how Gsonhandles stuff like this, and how I can use it?

任何人都可以向我解释或向我展示代码,如何Gson处理这样的东西,以及我如何使用它?

In short, why does...

简而言之,为什么...

String jsonInput = "{\"created_at\":\"Sat Feb 08 15:37:37 +0000 2014\",\"id\":432176397474623489\",\"user\":{\"id_str\":\"366301747\",\"name\":\"somethingClever\",\"screen_name\":\"somethingCoolAndClever\"}}";

Gson gson = new Gson();

Map<String, String> map = new HashMap<String, String>();

map = (Map<String, String>) gson.fromJson(jsonInput, map.getClass());

String name = map.get("name");

System.out.println(name);

... print out null?

...打印出来null

采纳答案by Sotirios Delimanolis

Forget about Java. You need to first understand the JSON format.

忘记 Java。您需要先了解JSON 格式

This is basically it

基本上就是这样

object
    {}
    { members }
members
    pair
    pair , members
pair
    string : value
array
    []
    [ elements ]
elements
    value 
    value , elements
value
    string
    number
    object
    array
    true
    false
    null

Your second JSON String(which has a missing ") is the following (use jsonlint.com to format)

您的第二个 JSON String(缺少")如下(使用 jsonlint.com 格式化)

{
    "created_at": "Sat Feb 08 15:37:37 +0000 2014",
    "id": "432176397474623489",
    "user": {
        "id_str": "366301747",
        "name": "somethingClever",
        "screen_name": "somethingCoolAndClever"
    }
}

The JSON is an object, outer {}, that contains three pairs, created_atwhich is a JSON string, idwhich is also a JSON string, and userwhich is a JSON object. That JSON object contains three more pairs which are all JSON strings.

JSON 是一个对象,外层{},包含三对,created_at一个是 JSON 字符串,id一个也是一个 JSON 字符串,user一个是一个 JSON 对象。该 JSON 对象包含另外三对都是 JSON 字符串。

You asked

你问

How could I assign the values specified within these inner-brackets to variables?

如何将这些内括号中指定的值分配给变量?

Most advanced JSON parsing/generating libraries are meant to convert JSON to Pojos and back.

大多数高级 JSON 解析/生成库旨在将 JSON 转换为 Pojos 并返回。

So you could map your JSON format to Java classes.

因此,您可以将 JSON 格式映射到 Java 类。

class Pojo {
    @SerializedName("created_at")
    private String createdAt;
    private String id;
    private User user;
}

class User {
    @SerializedName("id_str")
    private String idStr;
    private String name;
    @SerializedName("screen_name")
    private String screenName;
}

// with appropriate getters, setters, and a toString() method

Note the @SerializedNameso that you can keep using Java naming conventions for your fields.

请注意,@SerializedName以便您可以继续为您的字段使用 Java 命名约定。

You can now deserialize your JSON

您现在可以反序列化您的 JSON

Gson gson = new Gson();
Pojo pojo = gson.fromJson(jsonInput2, Pojo.class);
System.out.println(pojo);

would print

会打印

Pojo [createdAt=Sat Feb 08 15:37:37 +0000 2014, id=432176397474623489", user=User [idStr=366301747, name=somethingClever, screenName=somethingCoolAndClever]]

showing that all the fields were set correctly.

显示所有字段都设置正确。

Can anyone explain to me, or show me in code, how Gson handles stuff like this, and how I can use it?

任何人都可以向我解释,或用代码向我展示 Gson 如何处理这样的东西,以及我如何使用它?

The source code of Gson is freely available. You can find it online. It is complex and a source code explanation wouldn't fit here. Simply put, it uses the Classobject you provide to determine how it will map the JSON pairs. It looks at the corresponding class's fields. If those fields are other classes, then it recurs until it has constructed a map of everything it needs to deserialize.

Gson 的源代码是免费提供的。你可以在网上找到它。它很复杂,源代码解释不适合这里。简而言之,它使用Class您提供的对象来确定它将如何映射 JSON 对。它查看相应类的字段。如果这些字段是其他类,则它会重复执行,直到它构建了反序列化所需的所有内容的映射。



In short, why does...print out null?

简而言之,为什么...打印出空值?

Because your root JSON object, doesn't have a pair with name name. Instead of using Map, use Gson's JsonObjecttype.

因为您的根 JSON 对象没有 name 对name。不要使用Map,而是使用 Gson 的JsonObject类型。

JsonObject jsonObject = new Gson().fromJson(jsonInput2, JsonObject.class);

String name = jsonObject.get("user")       // get the 'user' JsonElement
                        .getAsJsonObject() // get it as a JsonObject
                        .get("name")       // get the nested 'name' JsonElement
                        .getAsString();    // get it as a String
System.out.println(name);

which prints

哪个打印

somethingClever

The above method class could have thrown a number of exceptions if they weren't the right type. If, for example, we had done

如果它们的类型不正确,上面的方法类可能会抛出许多异常。例如,如果我们做了

String name = jsonObject.get("user")       // get the 'user' JsonElement
                        .getAsJsonArray()  // get it as a JsonArray

it would fail because useris not a JSON array. Specifically, it would throw

它会失败,因为user它不是 JSON 数组。具体来说,它会抛出

Exception in thread "main" java.lang.IllegalStateException: This is not a JSON Array.
    at com.google.gson.JsonElement.getAsJsonArray(JsonElement.java:106)
    at com.spring.Example.main(Example.java:19)

So the JsonElementclass (which is the parent class of JsonObject, JsonArray, and a few others) provides methods to check what it is. See the javadoc.

因此JsonElement类(这是父类的JsonObjectJsonArray和其他几个人)提供了一些方法来检查它是什么。请参阅 javadoc。

回答by AKS

The JSON string has following structure:

JSON 字符串具有以下结构:

{
    created_at: "",
    id: "",
    user: {
            id_str: "",
            name: "",
            screen_name: ""
    }
 }

When you put the values in the map using the code:

当您使用代码将值放入地图时:

Map<String, Object> map = new HashMap<String, Object>();
map = (Map<String, Object>) gson.fromJson(jsonInput, map.getClass());

It has following key values:

它具有以下关键值:

created_at
id
user

and that's why you are able to use map.get("created_at").

这就是为什么您可以使用map.get("created_at").

Now, since you want to get the name of the user, you need to get the map of user:

现在,由于要获取用户的名称,因此需要获取用户的地图:

LinkedTreeMap<String, Object> userMap = (LinkedTreeMap<String, Object>) map.get("user");

In the userMap, you would get following key values:

在 中userMap,您将获得以下键值:

id_str
name
screen_name

Now, you can get the nameof the user

现在,你可以得到nameuser

String name = userMap.get("name");

回答by Smutje

useris a JsonObjectitself:

user是一个JsonObject本身:

JsonObject user = map.get("user");

回答by Mikkel L?kke

Ok. First of all JSON is short for "JavaScript Object Notation" so your assertion that "a JSON string is essentially a map" is incorrect. A JSON block is an object graph, described using the JavaScript language syntax. Since your trying to coerce an object graph to a Map of String, Sting kay value pairs, this is only going to work in cases where any given JSON object graph is essentially just that (so not very often). A more successful strategy would probably be gson.fromJson()which will convert your JSON to a proper Java object graph.

好的。首先,JSON 是“JavaScript Object Notation”的缩写,因此您关于“JSON 字符串本质上是地图”的断言是不正确的。JSON 块是一个对象图,使用 JavaScript 语言语法进行描述。由于您试图将对象图强制转换为字符串映射,Sting kay 值对,因此这仅在任何给定的 JSON 对象图本质上就是这样的情况下才有效(所以不是很常见)。更成功的策略可能是gson.fromJson()将您的 JSON 转换为适当的 Java 对象图。

回答by sagits

For people that come here searching for a way to convert LinkedTreeMap to object:

对于来这里寻找将 LinkedTreeMap 转换为 object 的方法的人

MyClass object = new Gson().fromJson(new Gson().toJson(((LinkedTreeMap<String, Object>) theLinkedTreeMapObject)), MyClass .class)

This was usefull for me when i needed to parse an generic object like:

当我需要解析一个通用对象时,这对我很有用:

Class fullObject {
  private String name;
  private String objectType;
  private Object objectFull;   
}

But i don't know which object the server was going to send. The objectFull will become a LinkedTreeMap

但我不知道服务器要发送哪个对象。objectFull 将成为 LinkedTreeMap