Skip to main content

[jsr353-experts] Re: [json-processing-spec users] Re: Json Null type: friend or foe?

  • From: Jitendra Kotamraju < >
  • To:
  • Subject: [jsr353-experts] Re: [json-processing-spec users] Re: Json Null type: friend or foe?
  • Date: Mon, 14 Jan 2013 16:13:48 -0800

On 01/14/2013 11:14 AM, Jonathan Fuerth wrote:
" type="cite">Sorry, I know this was a bit of a long message.

Executive Summary: I think we should remove JsonValue.NULL from the API. It does more harm than good.
If we remove it, what would be the alternative ? If we represent using null, that would cause more confusion
(i.e. whether mapping is there or not, if there is mapping, then it is null or not)

Scala's lift framework also uses something similar to JsonValue.NULL object. Perhaps, they must be facing similar
issue. I wonder how lift framework developers are dealing with it.

Jitu
" type="cite">

-Jonathan

On 2013-01-09, at 11:41 AM, Jonathan Fuerth wrote:

Consider the following JSON, an abbreviated Twitter Timeline response [1]:

[
  {
    "coordinates": null,
    "favorited": false,
    "truncated": false,
    "created_at": "Mon Sep 03 13:24:14 +0000 2012",
    "id_str": "242613977966850048",
    "entities": {
      "urls": [ ]
  },
  {
    "coordinates": {
     "coordinates": [
       121.0132101,
       14.5191613
     ],
     "type": "Point"
    },
    "favorited": false,
    "truncated": false,
    "created_at": "Mon Sep 03 08:08:0
    "id_str": "242534402280783873",
    "entities": {
      "urls": [ ]
  }
]

As you can see, the response is a JSON array of tweet objects. Each object contains an optional geolocation under the key "coordinates."

Here's some code that attempts to pull out the coordinates from the JSON array into a Java List<TweetCoordinatePoint>:

  private static List<TweetCoordinatePoint> extractTweetCoordinates(JsonArray tweets) {
    List<TweetCoordinatePoint> coordList = new ArrayList<TweetCoordinatePoint>();
    for (JsonValue tweetValue : tweets) {
      JsonObject tweet = (JsonObject) tweetValue;
      JsonObject coordinates = tweet.getValue("coordinates", JsonObject.class);
      if (coordinates != null && "Point".equals(coordinates.getStringValue("type"))) {
        JsonArray coordArray = coordinates.getValue("coordinates", JsonArray.class);
        coordList.add(new TweetCoordinatePoint(
                ((JsonNumber) coordArray.get(0)).getDoubleValue(),
                ((JsonNumber) coordArray.get(1)).getDoubleValue()));
      } else {
        coordList.add(null);
      }
    }
    return coordList;
  }

First of all, I think this is too much code for such a simple operation. But we can discuss that on a separate thread.

The point I want to make here is that this code compiles just fine, but it fails in a really surprising way: when it encounters a tweet without coordinates, it throws a ClassCastException on this line:

      JsonObject coordinates = tweet.getValue("coordinates", JsonObject.class);

which is before the (erroneous) null check.

I can think of three variations to correct the error under the current API, but they're all less satisfying than the above. Here's the best I could do:

  private static List<TweetCoordinatePoint> extractTweetCoordinates(JsonArray tweets) {
    List<TweetCoordinatePoint> coordList = new ArrayList<TweetCoordinatePoint>();
    for (JsonValue tweetValue : tweets) {
      JsonObject tweet = (JsonObject) tweetValue;
      JsonValue coordinates = tweet.get("coordinates");
      if (coordinates != JsonValue.NULL) {
        JsonObject coordObject = (JsonObject) coordinates;
        if ("Point".equals(coordObject.getStringValue("type"))) {
          JsonArray coordArray = coordObject.getValue("coordinates", JsonArray.class);
          coordList.add(new TweetCoordinatePoint(
                  ((JsonNumber) coordArray.get(0)).getDoubleValue(),
                  ((JsonNumber) coordArray.get(1)).getDoubleValue()));
        }
      } else {
        coordList.add(null);
      }
    }
    return coordList;
  }

This approach requires another local variable to first represent the coordinate as a JsonValue (so we can test it for null) and then an alias (coordObject) which has been downcast to JsonObject.

As a second possibility, I could avoid the need for two local variables by fetching "coordinates" twice from the map:

      JsonObject tweet = (JsonObject) tweetValue;
      if (tweet.get("coordinates") != JsonValue.NULL) {
        JsonObject coordObject = tweet.getValue("coordinates", JsonObject.class);

but that's not really great either.

The third option would be to pull out coordinates as a JsonValue, test it for null, and use repeated inline casts to JsonObject.


I do realize that all the preexisting JSON APIs for Java similarly use a special singleton to represent the JSON null value. It's certainly what someone would expect when approaching JSR353 after having used any other JSON library. But is this pattern helping or hindering correct use of the API? Might it improve both brevity and correct usage of the API if we dispose with JsonValue.NULL and use Java null in its place?

-Jonathan






[jsr353-experts] Json Null type: friend or foe?

Jonathan Fuerth 01/09/2013

[jsr353-experts] Re: Json Null type: friend or foe?

Jonathan Fuerth 01/14/2013

[jsr353-experts] Re: [json-processing-spec users] Re: Json Null type: friend or foe?

Jitendra Kotamraju 01/15/2013

[jsr353-experts] Re: [json-processing-spec users] Re: Re: Json Null type: friend or foe?

Jonathan Fuerth 01/15/2013

[jsr353-experts] Re: [json-processing-spec users] Re: Re: Re: Json Null type: friend or foe?

Jonathan Fuerth 01/15/2013

[jsr353-experts] Re: [json-processing-spec users] Re: Re: Re: Re: Json Null type: friend or foe?

Jitendra Kotamraju 01/15/2013

[jsr353-experts] Re: [json-processing-spec users] Re: Re: Re: Re: Re: Json Null type: friend or foe?

Jonathan Fuerth 01/15/2013

[jsr353-experts] Re: [json-processing-spec users] Re: Re: Re: Re: Re: Json Null type: friend or foe?

Jitendra Kotamraju 01/15/2013

[jsr353-experts] Re: [json-processing-spec users] Re: Re: Re: Re: Re: Json Null type: friend or foe?

Jonathan Fuerth 01/15/2013

[jsr353-experts] Re: [json-processing-spec users] Re: Re: Re: Re: Re: Json Null type: friend or foe?

Jonathan Fuerth 01/17/2013

[jsr353-experts] Re: [json-processing-spec users] Re: Re: Re: Re: Re: Json Null type: friend or foe?

Jitendra Kotamraju 01/18/2013
 
 
Close
loading
Please Confirm
Close