JSON to Java Objects, best practice for modeling the json stream

删除回忆录丶 提交于 2019-12-31 01:52:12

问题


I have a JSON stream being generated by a server side C++ program that is currently in development. I've been given a sample of the resulting JSON and I am concerned that I will have to parse the json by hand, that I won't be able to use normal class mapping provided by tools such as GSON or Jackson.

Please take a look at the following (somewhat) contrived example they have provided. The sections I'm concerned with are the meta data "serie" array having different parameters. The key - "key" for example is present in only one of the array elements. Will this not cause issues trying to map this array to a collection of a specific class?

Lastly, I am concerned that the "point" object is not similar. I have very limited understanding of JSON (being an old fashioned java swing developer) but the fact that the "point" key value pairs can be different - is a problem.

The whole idea for this json stream is to describe a table, with ways of showing progress and to provide a mechanism for asking for "more" from the underlying hardware. Also if you are wondering why, I am sharing this datastream with a thin client (html browser).

So am I correct that this will not easily convert to java objects?

{
  "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"
}

Thank you for any advice you can provide.

-D Klotz


回答1:


With GSON, assuming that the class you are deserializing into has fields for all the names that appear in the JSON, the fields not found in the JSON will just be left null:

https://sites.google.com/site/gson/gson-user-guide#TOC-Finer-Points-with-Objects

"While deserialization, a missing entry in JSON results in setting the corresponding field in the object to null"

Things get a little more complicated if arbitrary field names are allowed in the JSON - for example, if Point allows c1, c2, ... cn. But you can handle this with a custom deserializer.

https://sites.google.com/site/gson/gson-user-guide#TOC-Writing-a-Deserializer

Edit:

Here's how you might write a custom deserializer for 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;
}



回答2:


I'd be more concerned with what looks like metadata fields in the data stream. The top level 'abort' and 'more' attributes look like some kind of structured string which you may have to parse? Aside from that, you just need to model each Java object with the widest possible set of fields that will be sent from your external program. You don't have to worry if transmitted data has one or more of the fields missing, most JSON libraries will just deserialize a null in that case. Also, most of the JSON libraries will also allow you to specify that you want to ignore unknown incoming fields.

So between deserializing null for missing fields and ignoring extra fields, you should be good to go for your parse.




回答3:


No this isn't particularly hard to deserialize into Java objects. JSON doesn't have many clues about typing information other than their primitives. Most of the concern about loosing type information can be recovered either by looking at the object you want to deserialize into, or have the user provide the object they want to deserialize into. That's precisely how flexjson works, and you have a lot of flexibility to define at each point how to deserialize it. It comes with sensible defaults for most problems, but you can always attach an ObjectFactory to specific class or path with in the JSON stream.

http://flexjson.sourceforge.net



来源:https://stackoverflow.com/questions/9844494/json-to-java-objects-best-practice-for-modeling-the-json-stream

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!