Gson,JSON和LinkedTreeMap的微妙之处

ViR*_*LiC 12 java json gson

我最近开始玩JSON字符串,并被告知谷歌自己的库Gson,是处理这些的新的和时髦的方式.

我理解它的方式是JSON字符串本质上是一个地图.每个变量指向字符串中的值.

例如:

String jsonInput2 = "{\"created_at\":\"Sat Feb 08 15:37:37 +0000 2014\",\"id\":432176397474623489\"}
Run Code Online (Sandbox Code Playgroud)

到目前为止,一切都很好.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");
Run Code Online (Sandbox Code Playgroud)

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

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

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

我的问题是这些"括号内的括号"如何适用于该user部分JSON

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

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

简而言之,为什么......

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);
Run Code Online (Sandbox Code Playgroud)

打印出来null

Sot*_*lis 31

忘了Java.您需要先了解JSON格式.基本上就是这样

object
    {}
    { members }
members
    pair
    pair , members
pair
    string : value
array
    []
    [ elements ]
elements
    value 
    value , elements
value
    string
    number
    object
    array
    true
    false
    null
Run Code Online (Sandbox Code Playgroud)

您的第二个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"
    }
}
Run Code Online (Sandbox Code Playgroud)

JSON是一个对象,outer {},包含三对,created_at它是一个JSON字符串,id也是一个JSON字符串,user它是一个JSON对象.该JSON对象包含三对,都是JSON字符串.

您询问

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

最先进的JSON解析/生成库旨在将JSON转换为Pojos并返回.

因此,您可以将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
Run Code Online (Sandbox Code Playgroud)

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

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

Gson gson = new Gson();
Pojo pojo = gson.fromJson(jsonInput2, Pojo.class);
System.out.println(pojo);
Run Code Online (Sandbox Code Playgroud)

会打印

Pojo [createdAt=Sat Feb 08 15:37:37 +0000 2014, id=432176397474623489", user=User [idStr=366301747, name=somethingClever, screenName=somethingCoolAndClever]]
Run Code Online (Sandbox Code Playgroud)

显示所有字段都已正确设置.

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

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


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

因为你的根JSON对象,没有名字对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);
Run Code Online (Sandbox Code Playgroud)

打印

somethingClever
Run Code Online (Sandbox Code Playgroud)

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

String name = jsonObject.get("user")       // get the 'user' JsonElement
                        .getAsJsonArray()  // get it as a JsonArray
Run Code Online (Sandbox Code Playgroud)

它会失败,因为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)
Run Code Online (Sandbox Code Playgroud)

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


sag*_*its 7

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

MyClass object = new Gson().fromJson(new Gson().toJson(((LinkedTreeMap<String, Object>) theLinkedTreeMapObject)), MyClass .class)
Run Code Online (Sandbox Code Playgroud)

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

Class fullObject {
  private String name;
  private String objectType;
  private Object objectFull;   
}
Run Code Online (Sandbox Code Playgroud)

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


AKS*_*AKS 6

JSON字符串具有以下结构:

{
    created_at: "",
    id: "",
    user: {
            id_str: "",
            name: "",
            screen_name: ""
    }
 }
Run Code Online (Sandbox Code Playgroud)

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

Map<String, Object> map = new HashMap<String, Object>();
map = (Map<String, Object>) gson.fromJson(jsonInput, map.getClass());
Run Code Online (Sandbox Code Playgroud)

它具有以下关键值:

created_at
id
user
Run Code Online (Sandbox Code Playgroud)

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

现在,由于要获取用户名,因此需要获取用户映射:

LinkedTreeMap<String, Object> userMap = (LinkedTreeMap<String, Object>) map.get("user");
Run Code Online (Sandbox Code Playgroud)

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

id_str
name
screen_name
Run Code Online (Sandbox Code Playgroud)

现在,你可以得到nameuser

String name = userMap.get("name");
Run Code Online (Sandbox Code Playgroud)