我有一个JSON流由当前正在开发的服务器端C ++程序生成。我得到了一个结果JSON的样本,我担心我必须手工解析json,我将无法使用GSON或Jackson等工具提供的普通类映射。
请看一下他们提供的以下(有些)人为的例子。我关注的部分是具有不同参数的元数据“serie”数组。键 - “键”例如仅存在于一个数组元素中。这不会导致尝试将此数组映射到特定类的集合时出现问题吗?
最后,我担心“点”对象并不相似。我对JSON(作为一个老式的java swing开发人员)的理解非常有限,但“点”键值对可以不同的事实 - 是一个问题。
这个json流的整个想法是描述一个表,其中包含显示进度的方法,并提供一种从底层硬件中寻求“更多”的机制。此外,如果您想知道为什么,我将与瘦客户端(HTML浏览器)共享此数据流。
所以我认为这不会轻易转换为java对象吗?
{
"abort": "abort;session=sessionname",
"data": {
"metadata": [
{
"protocol": "HTTP",
"serie": [
{
"name": "k1",
"description": "xDR ID",
"tooltip": "ASDR Unique Identifier - UiD",
"type": "int64",
"key": "1"
},
{
"name": "c1",
"description": "Answered",
"tooltip": "Request with Response",
"type": "bool"
},
{
"name": "c2",
"description": "Active",
"tooltip": "Session status: active or closed/down",
"type": "bool"
}
]
},
{
"protocol": "DNS",
"serie": [
{
"name": "k1",
"description": "xDR ID",
"tooltip": "ASDR Unique Identifier - UiD",
"type": "int64",
"key": "1"
},
{
"name": "k2",
"description": "Transaction ID",
"type": "int64",
"key": "1",
"display": "number"
},
{
"name": "k3",
"description": "Client",
"tooltip": "Source IP Address",
"type": "string",
"key": "1",
"display": "ip"
}
]
}
],
"summary": [
{
"timestamp": "1331192727",
"protocol": "HTTP",
"activity": "www.google.com",
"results": "OK",
"point": {
"k1": "1",
"c1": "true",
"c2": "true"
}
},
{
"timestamp": "1331192727",
"protocol": "DNS",
"activity": "www.google.com",
"results": "OK",
"point": {
"k1": "1",
"k2": "1.1.4.229"
}
}
]
},
"progress": {
"perc": "100"
},
"more": "13,39,1331192727,1331192760,27236,1.1.4.229,limit=1000,session=sessionname"
}
感谢您提供任何建议。
-D Klotz
答案 0 :(得分:4)
使用GSON,假设您要反序列化的类具有JSON中出现的所有名称的字段,那么JSON中找不到的字段将保留为null:
https://sites.google.com/site/gson/gson-user-guide#TOC-Finer-Points-with-Objects
“反序列化时,JSON中缺少的条目导致将对象中的相应字段设置为null”
如果JSON中允许任意字段名称,事情会变得复杂一些 - 例如,如果Point允许c1,c2,... cn。但您可以使用自定义反序列化器处理此问题。
https://sites.google.com/site/gson/gson-user-guide#TOC-Writing-a-Deserializer
修改强>
以下是为Point编写自定义反序列化器的方法:
private class DateTimeDeserializer implements JsonDeserializer<Point> {
public Point deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
List<PointPart> parts = Lists.newArrayList();
for(Map.Entry<String,JsonElement> entry :
json.getAsJsonObject().entrySet()) {
char type = ;
int index = Integer.parseInt(entry.getKey().substring(1)) - 1;
while(parts.size() <= index) {
parts.add(new PointPart());
}
PointPart part = parts.get(index);
switch(entry.getKey().charAt(0)) {
case 'c':
part.c = entry.getValue().getAsBoolean();
break;
case 'k':
part.k = entry.getValue().getAsInt();
break;
}
}
return new Point(parts);
}
}
class Point {
List<PointPart> parts;
Point(List<PointPart> parts) {
this.parts = parts;
}
}
class PointPart {
boolean c;
int k;
}
答案 1 :(得分:2)
我更关心的是数据流中的元数据字段。顶级&#39;中止&#39;和更多&#39;属性看起来像某种结构化的字符串,您可能需要解析?除此之外,您只需要使用从外部程序发送的最广泛的字段集来为每个Java对象建模。如果传输的数据中缺少一个或多个字段,您不必担心,大多数JSON库只会在这种情况下反序列化null。此外,大多数JSON库还允许您指定要忽略未知的传入字段。
因此,在为缺少的字段反序列化null和忽略额外的字段之间,你应该很好地进行解析。
答案 2 :(得分:1)
这不是特别难以反序列化为Java对象。 JSON没有很多关于键入除基元之外的信息的线索。通过查看要反序列化的对象或让用户提供要反序列化的对象,可以恢复对丢失类型信息的大多数担忧。这正是flexjson的工作方式,并且您可以在每个点定义如何反序列化它。它为大多数问题提供了合理的默认值,但您始终可以在JSON流中将ObjectFactory附加到特定的类或路径。