Representing null in JSON
gson, jackson, json, null
Solution
Let's evaluate the parsing of each:
http://jsfiddle.net/brandonscript/Y2dGv/
var json1 = '{}';
var json2 = '{"myCount": null}';
var json3 = '{"myCount": 0}';
var json4 = '{"myString": ""}';
var json5 = '{"myString": "null"}';
var json6 = '{"myArray": []}';
console.log(JSON.parse(json1)); // {}
console.log(JSON.parse(json2)); // {myCount: null}
console.log(JSON.parse(json3)); // {myCount: 0}
console.log(JSON.parse(json4)); // {myString: ""}
console.log(JSON.parse(json5)); // {myString: "null"}
console.log(JSON.parse(json6)); // {myArray: []}
The tl;dr here:
The fragment in the json2 variable is the way the JSON spec indicates `null` should be represented. But as always, it depends on what you're doing -- sometimes the "right" way to do it doesn't always work for your situation. Use your judgement and make an informed decision.
JSON1 `{}`
This returns an empty object. There is no data there, and it's only going to tell you that whatever key you're looking for (be it `myCount` or something else) is of type `undefined`.
JSON2 `{"myCount": null}`
In this case, `myCount` is actually defined, albeit its value is `null`. This is not the same as both "not `undefined` and not `null`", and if you were testing for one condition or the other, this might succeed whereas JSON1 would fail.
This is the definitive way to represent `null` per the JSON spec.
JSON3 `{"myCount": 0}`
In this case, myCount is 0. That's not the same as `null`, and it's not the same as `false`. If your conditional statement evaluates `myCount > 0`, then this might be worthwhile to have. Moreover, if you're running calculations based on the value here, 0 could be useful. If you're trying to test for `null` however, this is actually not going to work at all.
JSON4 `{"myString": ""}`
In this case, you're getting an empty string. Again, as with JSON2, it's defined, but it's empty. You could test for `if (obj.myString == "")` but you could not test for `null` or `undefined`.
JSON5 `{"myString": "null"}`
This is probably going to get you in trouble, because you're setting the string value to null; in this case, `obj.myString == "null"` however it is not `== null`.
JSON6 `{"myArray": []}`
This will tell you that your array `myArray` exists, but it's empty. This is useful if you're trying to perform a count or evaluation on `myArray`. For instance, say you wanted to evaluate the number of photos a user posted - you could do `myArray.length` and it would return `0`: defined, but no photos posted.
Problem
What is the preferred method for returning null values in JSON? Is there a different preference for primitives? For example, if my object on the server has an Integer called "myCount" with no value, the most correct JSON for that value would be: ``` {} ``` or ``` { "myCount": null } ``` or ``` { "myCount": 0 } ``` Same question for Strings - if I have a null string "myString" on the server, is the best JSON: ``` {} ``` or ``` { "myString": null } ``` or ``` { "myString": "" } ``` or (lord help me) ``` { "myString": "null" } ``` I like the convention for collections to be represented in the JSON as an empty collection http://jtechies.blogspot.nl/2012/07/item-43-return-empty-arrays-or.html An empty Array would be represented: ``` { "myArray": [] } ``` EDIT Summary The 'personal preference' argument seems realistic, but short sighted in that, as a community we will be consuming an ever greater number of disparate services/sources. Conventions for JSON structure would help normalize consumption and reuse of said services. As far as establishing a standard, I would suggest adopting most of the Jackson conventions with a few exceptions: - Objects are preferred over primitives. - Empty collections are preferred over null. - Objects with no value are represented as null. - Primitives return their value. If you are returning a JSON object with mostly null values, you may have a candidate for refactoring into multiple services. ``` { "value1": null, "value2": null, "text1": null, "text2": "hello", "intValue": 0, //use primitive only if you are absolutely sure the answer is 0 "myList": [], "myEmptyList": null, //NOT BEST PRACTICE - return [] instead "boolean1": null, //use primitive only if you are absolutely sure the answer is true/false "littleboolean": false } ``` The above JSON was generated from the following Java class. ``` package jackson; import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.databind.ObjectMapper; public class JacksonApp { public static class Data { public Integer value1; public Integer value2; public String text1; public String text2 = "hello"; public int intValue; public List<Object> myList = new ArrayList<Object>(); public List<Object> myEmptyList; public Boolean boolean1; public boolean littleboolean; } public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); System.out.println(mapper.writeValueAsString(new Data())); } } ``` Maven dependency: ``` <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.3.0</version> </dependency> ```