使用GSON解析JSON文件

时间:2012-05-19 19:57:34

标签: java json parsing nested gson

我在将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更改为Map

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

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

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

感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

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

有了这个,您应该能够将JSON反序列化为对象。此外,因为在服务器端,您将Node集合表示为List,所以我将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数组,而Maps通常更适合在父对象内表示几个JSON对象。

答案 1 :(得分:1)

如果确实拥有控件 JSON的格式,我建议the overall list structure that jmort253 suggests in his answer,即[{"name":"Speidy", ... },{"name":"ShadowSlayer272", ... }]

如果您对生成的JSON有无控制,则有两种方法可以将问题{"Speidy":{ ... },"ShadowSlayer272":{ ... }}中的JSON代码段映射为GSON:

  • 没有您的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);