JSON到Java Objects,是建模json流的最佳实践

时间:2012-03-23 18:18:09

标签: java json deserialization

我有一个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

3 个答案:

答案 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附加到特定的类或路径。

http://flexjson.sourceforge.net