Java Gson、JSON和LinkedTreeMap的微妙之处

Java Gson、JSON和LinkedTreeMap的微妙之处,java,json,gson,Java,Json,Gson,我最近开始玩弄JSON字符串,有人告诉我,谷歌自己的库Gson,是处理这些字符串的新方法 我的理解是,JSON字符串本质上是一个映射。其中每个变量都指向字符串中的一个值 例如: String jsonInput2 = "{\"created_at\":\"Sat Feb 08 15:37:37 +0000 2014\",\"id\":432176397474623489\"} 到目前为止,一切顺利。创建此JSON字符串的时间等信息可通过以下代码分配给变量: Gson gson = new Gs

我最近开始玩弄
JSON
字符串,有人告诉我,谷歌自己的库
Gson
,是处理这些字符串的新方法

我的理解是,
JSON
字符串本质上是一个映射。其中每个变量都指向字符串中的一个值

例如:

String jsonInput2 = "{\"created_at\":\"Sat Feb 08 15:37:37 +0000 2014\",\"id\":432176397474623489\"}
到目前为止,一切顺利。创建此
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");
我的问题是这些“括号内的括号”如何适用于
JSON
user
部分

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

有谁能向我解释一下,或者用代码向我展示一下,
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);
String jsonInput=“{\”created\u at\”:\“Sat Feb 08 15:37:37+0000 2014\”,“id\”:4321763397474623489\,“user\:{\“id\u str\”:“366301747\”,“name\”:“somethinggleer\”,“screen\u name\:“somethingCoolandgleer\”;
Gson Gson=新的Gson();
Map Map=newhashmap();
map=(map)gson.fromJson(jsonInput,map.getClass());
String name=map.get(“name”);
System.out.println(名称);

…打印出
null

JSON字符串具有以下结构:

{
    created_at: "",
    id: "",
    user: {
            id_str: "",
            name: "",
            screen_name: ""
    }
 }
使用代码将值放入地图时:

Map<String, Object> map = new HashMap<String, Object>();
map = (Map<String, Object>) gson.fromJson(jsonInput, map.getClass());
这就是为什么您能够使用
map.get(“created_at”)

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

LinkedTreeMap<String, Object> userMap = (LinkedTreeMap<String, Object>) map.get("user");
现在,您可以获得
用户的
名称

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

user
本身就是一个
JsonObject
对象:

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

忘了Java吧,你需要先了解Java

基本上就是这样

object
    {}
    { members }
members
    pair
    pair , members
pair
    string : value
array
    []
    [ elements ]
elements
    value 
    value , elements
value
    string
    number
    object
    array
    true
    false
    null
您的第二个JSON
字符串(缺少
)如下所示(使用jsonlint.com格式化)

JSON是一个对象,外部为
{}
,包含三对,
处创建,这是一个JSON字符串,
id
也是一个JSON字符串,
user
是一个JSON对象。该JSON对象还包含三对JSON字符串

你问

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

最高级的JSON解析/生成库旨在将JSON转换为POJO并返回

因此,您可以将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
请注意,这样您就可以继续对字段使用Java命名约定

现在可以反序列化JSON了

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

Pojo [createdAt=Sat Feb 08 15:37:37 +0000 2014, id=432176397474623489", user=User [idStr=366301747, name=somethingClever, screenName=somethingCoolAndClever]]
显示所有字段都已正确设置

有谁能向我解释一下,或者用代码向我展示一下,Gson是如何处理这样的事情的,以及我是如何使用它的

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


简而言之,为什么…打印为空

因为您的根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);
哪张照片

somethingClever
如果异常类型不正确,上述方法类可能会引发大量异常。例如,如果我们做了

String name = jsonObject.get("user")       // get the 'user' JsonElement
                        .getAsJsonArray()  // get it as a JsonArray
它将失败,因为
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)

因此该类(它是
JsonObject
JsonArray
和其他一些类的父类)提供了检查它是什么的方法。请参阅javadoc。

确定。首先,JSON是“JavaScript对象表示法”的缩写,因此您关于“JSON字符串本质上是一个映射”的断言是不正确的。JSON块是一个对象图,使用JavaScript语言语法描述。由于您试图将一个对象图强制为一个字符串、Sting-kay值对的映射,因此这只适用于任何给定JSON对象图本质上就是这样的情况(所以不太常见)。一个更成功的策略可能是
gson.fromJson()
,它将把你的JSON转换成一个合适的Java对象图。

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


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

它可能是,但这不起作用,因为
map
声明为
map
。不,在这种情况下,它将默认为
LinkedTreeMap
。Gson不知道
JsonObject
,除非你告诉它。这个
Gson.fromJson(map.get(“user”)
将失败。
map.getUser(“user”)
返回一个
LinkedTreeMap
@AKS如何处理name=userMap.get(“name”)字符串中的name有时不可用的情况?最好、最容易理解的答案。谢谢Sotirios!@ViRALiC不客气。我的最佳建议是在研究Gson之前熟悉JSON。谢谢。这让我省去了很多悲伤!非常感谢,无法回答这件事让我损失了一次采访。最后找到了解决办法。
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);
somethingClever
String name = jsonObject.get("user")       // get the 'user' JsonElement
                        .getAsJsonArray()  // get it as a JsonArray
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)
MyClass object = new Gson().fromJson(new Gson().toJson(((LinkedTreeMap<String, Object>) theLinkedTreeMapObject)), MyClass .class)
Class fullObject {
  private String name;
  private String objectType;
  private Object objectFull;   
}