我在将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;
}
保持节点文件相同。然后该字符串将是属性名称,即Speidy
或ShadowSlayer272
。但是,gson从不对节点做任何事情,当我尝试getNodes()
时,它会返回一个null
对象。
感谢您的帮助。
答案 0 :(得分:2)
您列出了一个名称,您可能想要表示一个值,作为对象的属性名称。相反,在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对象。
答案 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);