1

我在将 JSON 文件读入 POJO 时遇到问题。让我给你一个我的 JSON 文件的片段:

 {
    "Speidy": {
        "factionId": "2",
        "role": "ADMIN",
        "title": "",
        "power": 9.692296666666667,
        "powerBoost": 0.0,
        "lastPowerUpdateTime": 1337023306922,
        "lastLoginTime": 1337023306922,
        "chatMode": "PUBLIC"
    },
    "ShadowSlayer272": {
        "factionId": "2",
        "role": "NORMAL",
        "title": "",
        "power": 0.8673466666666667,
        "powerBoost": 0.0,
        "lastPowerUpdateTime": 1336945426926,
        "lastLoginTime": 1336945426926,
        "chatMode": "PUBLIC"
    },

我的问题是第一个“节点”是完全随机的,即如果每次都不同,我该如何为其制作 POJO 文件?

我的子数据 POJO 文件是这样的:

public class Node {
    private int factionId = 0;
    private String role = "";
    private String title = "";
    private double power = 0.0;
    private double powerBoost = 0.0;
    private int lastPowerUpdateTime = 0;
    private int lastLoginTime = 0;
    private String chatMode = "";
}

然后我的另一个 POJO 文件是这样的:

public class Container {
    private List<Node> nodes; //What should nodes be for GSON to get each random one?

    public List<Node> getNodes() {
        return nodes;
    }
}

我感谢所有帮助,谢谢。

更新

我尝试将其更改List为 a Map

public class Container {
    private Map<String,Node> nodes;

    public Map<String,Node> getNodes() {
        return nodes;
    }

同时保持节点文件相同。该字符串将是属性名称,即SpeidyShadowSlayer272。但是,gson 从不对节点做任何事情,当我尝试和 to 时getNodes(),它会返回一个null对象。

谢谢您的帮助。

4

2 回答 2

2

您正在列出看似名称的名称,您可能打算表示一个值,作为对象的属性名称。相反,将名称包含在 JSON 字符串中,并为其分配一个属性名称,该名称实际上将作为私有变量(带有 getter 和 setter)出现在您的 Java Node 类中。

有了这个,您应该能够将您的 JSON 反序列化回一个对象。此外,由于在服务器端您将节点集合表示为列表,因此我将 JSON 转换为包含两个对象的数组。在 JavaScript 中,您可以使用 和 来访问它们node[0].namenode[1].name这相当于nodes.get(0).getName()在服务器端:

[
    {
        "name" : "Speidy",
        "factionId": "2",
        "role": "ADMIN",
        "title": "",
        "power": 9.692296666666667,
        "powerBoost": 0.0,
        "lastPowerUpdateTime": 1337023306922,
        "lastLoginTime": 1337023306922,
        "chatMode": "PUBLIC"
    },
    {
        "name" : "ShadowSlayer272",
        "factionId": "2",
        "role": "NORMAL",
        "title": "",
        "power": 0.8673466666666667,
        "powerBoost": 0.0,
        "lastPowerUpdateTime": 1336945426926,
        "lastLoginTime": 1336945426926,
        "chatMode": "PUBLIC"
    }
]

public class Node {
    private String name = "";

    private int factionId = 0;
    private String role = "";
    private String title = "";
    private double power = 0.0;
    private double powerBoost = 0.0;
    private int lastPowerUpdateTime = 0;
    private int lastLoginTime = 0;
    private String chatMode = "";
}

话虽如此,如果您确实需要将该名称用作属性名称,请考虑将 JSON 反序列化为 HashMap 而不是 List。列表通常映射到 JSON 数组,而 Map 通常更适合表示父对象内的多个 JSON 对象。

于 2012-05-19T20:06:41.790 回答
1

如果您确实可以控制JSON 的格式,我建议jmort253 在他的回答中建议的整体列表结构,即[{"name":"Speidy", ... },{"name":"ShadowSlayer272", ... }].

如果您无法控制{"Speidy":{ ... },"ShadowSlayer272":{ ... }}生成的 JSON,这里有两种方法可以使用 Gson映射 JSON 片段,例如您的问题中的那个:

  • 没有你的Container班级和一点TypeToken巫术:

    // Ask Gson to deserialize the JSON snippet into a Map<String, Node>.
    Type type = new TypeToken<Map<String, Node>>() {}.getType();
    Map<String, Node> nodes = gson.fromJson(json, type);
    
  • 您的Container班级和自定义JsonDeserializer

    class ContainerDeserializer implements JsonDeserializer<Container> {
      public Container deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
          throws JsonParseException {
        List<Node> nodes = new ArrayList<Node>();
        JsonObject players = json.getAsJsonObject();
        for (Entry<String, JsonElement> player : players.entrySet()) {
          String playerName = player.getKey();
          JsonElement playerData = player.getValue();
          // Use Gson to deserialize all fields except
          // for the name into a Node instance ...
          Node node = context.deserialize(playerData, Node.class);
          node.name = playerName; // ... then set the name.
          nodes.add(node);
        }
        return new Container(nodes);
      }
    }
    

    这假设一个构造函数,Container(List<Node>)并允许Container实例是不可变的,这通常是一件好事。

    像这样注册并使用自定义序列化程序:

    GsonBuilder builder = new GsonBuilder();
    // Tell Gson to use the custom ContainerDeserializer whenever
    // it's asked for a Container instance.
    builder.registerTypeAdapter(Container.class, new ContainerDeserializer());
    Gson gson = builder.create();
    
    // Ask Gson to create Container instance from your JSON snippet.
    Container container = gson.fromJson(json, Container.class);
    
于 2012-05-21T21:36:33.973 回答