首页 > 解决方案 > 子类实例变量如何与父类实例联系

问题描述

我试图在下面的代码片段中了解父类和子类实例范围或它们的行为。(通过 GSON 框架了解功能)

private static JsonObject jsonObjectAddress = new JsonObject();
jsonObjectAddress = jsonParser.parse(bufferRead).getAsJsonObject().getAsJsonObject("address");
Set<Entry<String, JsonElement>> entrySetProperties = jsonObjectAddress.entrySet();

想了解:

jsonParser.parse(bufferRead)返回作为JsonElement类的父类的类实例JsonObject

并且JsonObject类中有以下 Instnce 变量,它由所有带有键值对的 JSON 属性组成。

private final LinkedTreeMap<String, JsonElement> members =
      new LinkedTreeMap<String, JsonElement>();

我只是想知道,在哪里和谁在填充这个members,因为它作为实例变量存在于孩子的类中并且jsonParser.parse(bufferRead)只返回 JsonElement 实例......!

我可以知道它是如何工作的......?任何帮助将不胜感激以了解更多...!

更新:

当我运行这个

jsonObjectAddress = jsonParser.parse(bufferRead).getAsJsonObject();
Set<Entry<String, JsonElement>> entrySetProperties = jsonObjectAddress.entrySet();
for(Map.Entry<String, JsonElement> entry: entrySetProperties) {

    System.out.println(entry.getValue().getClass());

    System.out.println(entry.getKey()+":"+ entry.getValue());
}

它给了我以下结果

class com.google.gson.JsonPrimitive
empID:100
class com.google.gson.JsonPrimitive
name:"David"
class com.google.gson.JsonPrimitive
permanent:false
class com.google.gson.JsonObject
address:{"street":"BTM 1st Stage","city":"Bangalore","zipcode":560100}
class com.google.gson.JsonArray
phoneNumbers:[123456,987654]
class com.google.gson.JsonPrimitive
role:"Manager"
class com.google.gson.JsonArray
cities:["Los Angeles","New York"]
class com.google.gson.JsonObject
properties:{"age":"28 years","salary":"1000 Rs"}

上面的结果是类的memberindtance 变量的值JsonObject。但是,如果您看到 set 中的值之一member也是 JsonObject 本身。

所以如果我这样跑

jsonObjectAddress = jsonParser.parse(bufferRead).getAsJsonObject().getAsJsonObject("address");

它表示JsonObject存储在键名addreess中的相同类型值,member并显示如下结果

class com.google.gson.JsonPrimitive
street:"BTM 1st Stage"
class com.google.gson.JsonPrimitive
city:"Bangalore"
class com.google.gson.JsonPrimitive
zipcode:560100

在这里很困惑,addresskey inmember是有JsonObject,所以当我们只提取地址时,它如何返回 entryset()...?

标签: javaoopgson

解决方案


解析器创建一个 JsonElements 树作为解析 JSON 字符串的结果,它的返回值是作为该树根的元素。谁“负责”填写成员集的答案是解析器;这就是解析器解析输入所做的事情。

无需“取得联系”;有一个相当于 JSON 的数据结构。例如,如果您的 JSON 是

{ "stuff" : { "foo" : "F" , "bar" : "B" } }

那么顶层 JsonObject 中的映射有一个条目,键为“stuff”,该条目的值是一个 JsonObject,其映射有两个条目,键为“foo”和“bar”,其值为 JsonPrimitive 值,在这种情况下字符串。

随后的“获取”操作从该树中检索节点。


当你写这个:

private static JsonObject jsonObjectAddress = new JsonObject();

您分配了一个从未使用过的新 JsonObject,因为在下一行

 jsonObjectAddress = ...

您将变量设置为不同的 JsonObject,它存在于解析器创建的树结构中。


再编辑一些:

也许我误解了您对父/子术语的使用。我将其解释为引用对象树中的父/子关系。但似乎您也提到了超类/子类关系。

我认为你以错误的方式看待它。没有单独的“JsonObject 实例”和“JsonElement 实例”。(至少在概念上)只有一个对象;该对象是一个 JsonElement,并且(在这种特殊情况下)它也是一个 JsonObject。

这就是 Java 类的工作方式。

因此,当您从解析树中获取节点时,它会被视为 JsonElement,因为这是所有可能性的基本类型。该元素可以是 JsonObject、JsonPrimitive、JsonArray 或 JsonNull。当您调用“getAsJsonObject”时,您基本上是在说您现在想要将您拥有的元素视为一个对象(并且在内部 GSON 将检查这样做是否有意义)。


在您更新问题后添加。

jsonObjectAddress = 
    jsonParser.parse(bufferRead) // builds tree, returns
                                 // root node as JsonElement
    .getAsJsonObject()           // returns that element (the root)
                                 // now considered as JsonObject
    .getAsJsonObject("address"); // looks up "address" in the members
                                 // map of the root, finds a JsonElement,
                                 // returns that element considered as 
                                 // a JsonObject
    // and that last is what you store in jsonObjectAddress.

每个 JsonElement 都是 JsonPrimitive、JsonObject、JsonArray 或 JsonNull。我们的兴趣在于 JsonObject;根据定义,它们被构造成更多的领域。每个 JsonObject 都有一个名为“members”的映射,用于枚举对象的字段。

根对象(代表整个 JSON 字符串)具有名为“名称”、“地址”、“角色”等的字段,因此其映射包含键“名称”、“地址”、“角色”等。表示“地址”的对象具有名为“街道”、“城市”等的字段,因此它的地图包含“街道”、“城市”等键。


推荐阅读