[英]Parsing a JSON file with 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;
}
}
感谢所有的帮助,谢谢。
UPDATE
我尝试将List
更改为Map
:
public class Container {
private Map<String,Node> nodes;
public Map<String,Node> getNodes() {
return nodes;
}
同时保持节点文件相同。 然后该字符串将是属性名称,即Speidy
或ShadowSlayer272
。 但是,gson从不对节点做任何事情,当我尝试getNodes getNodes()
,它返回一个null
对象。
谢谢您的帮助。
您列出了一个名称,您可能想要表示一个值,作为对象的属性名称。 相反,在JSON字符串中包含该名称,并为其分配一个属性名称,该名称实际上将在Java Node类中显示为私有变量(带有getter和setter)。
有了这个,您应该能够将JSON反序列化为对象。 此外,因为在服务器端,您将Node集合表示为List,所以我将JSON转换为包含两个对象的数组。 在JavaScript中,您可以将它们作为node[0].name
和node[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对象。
如果你确实控制了JSON的格式,我建议jmort253在他的答案中建议的整体列表结构 ,即[{"name":"Speidy", ... },{"name":"ShadowSlayer272", ... }]
。
如果您无法控制生成的JSON,可以通过以下两种方式映射JSON代码段,例如您的问题{"Speidy":{ ... },"ShadowSlayer272":{ ... }}
与Gson:
没有您的Container
类和一点TypeToken
伏都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);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.