Gson,JSON和LinkedTreeMap的微妙之处

vfwfrxfs  于 2023-10-18  发布在  其他
关注(0)|答案(5)|浏览(159)

我最近开始使用JSON字符串,并被告知Google自己的库Gson是处理这些字符串的新方法。
我的理解是,JSON字符串本质上是一个map。其中每个变量都指向字符串中的一个值。
举例来说:

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字符串的扩展:

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

我的问题是这些“括号中的括号”如何适用于JSONuser部分?
如何将这些内括号中指定的值赋给变量?
谁能给我解释一下,或者用代码演示一下,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);

. print out null

de90aj5v

de90aj5v1#

忘记Java。首先,你需要了解JSON format
基本上就是这样

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

第二个JSON String(缺少")如下所示(使用https://jsonlint.com/进行格式化)

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

JSON是一个对象,外部{},它包含三对,created_at是JSON字符串,id也是JSON字符串,user是JSON对象。这个JSON对象包含另外三对JSON字符串。
你问
如何将这些内括号中指定的值赋给变量?
大多数高级JSON解析/生成库都是用来将JSON转换为Pojos并返回的。
所以你可以将JSON格式Map到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

请注意@SerializedNamex 1 e3f1x,以便您可以继续使用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的源代码是免费的。你可以在网上找到。它很复杂,源代码解释不适合这里。简单地说,它使用您提供的Class对象来确定如何MapJSON对。它查看相应类的字段。如果这些字段是其他类,那么它会递归,直到它构建了一个Map,Map了它所需要的所有内容。
简而言之,为什么. print out null?
因为你的根JSON对象没有一个名为name的对。使用Gson的JsonObject类型而不是Map

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)

所以JsonElement(JavaDoc)类(它是JsonObjectJsonArray和其他一些类的父类)提供了检查它是什么的方法。查看javadoc。

ih99xse1

ih99xse12#

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

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;   
}

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

xxls0lw8

xxls0lw83#

JSON字符串具有以下结构:

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

当您使用代码将值放入Map中时:

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

它具有以下关键价值:

created_at
id
user

这就是为什么你可以使用map.get("created_at")
现在,既然你想得到用户的名字,你需要得到用户的map:

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

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

id_str
name
screen_name

现在,您可以获得username

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

flmtquvp4#

userJsonObject本身:

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

ie3xauqp5#

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

相关问题