JSON-java
JSON-java copied to clipboard
Creating JSONObject from Map vs String misses null values
If we create a JSONObject from a string containing null values, those are parsed internally as JSONObject.NULL [see 1]. However, when creating a JSONObject from a Map, null values are ignored [see 2].
This is a problem since we have an inconsistency. Either both cases ignore nulls (this wouldn't represent reality), or both convert Java nulls to JSONObject.NULL.
1: https://github.com/stleary/JSON-java/blob/7d6b76de375f8fbde93226ed77dbf51e4c70e29a/src/main/java/org/json/JSONObject.java#L2309-L2311 2: (there's no ELSE) https://github.com/stleary/JSON-java/blob/7d6b76de375f8fbde93226ed77dbf51e4c70e29a/src/main/java/org/json/JSONObject.java#L307-L309
This is as-designed.
When parsing a String, we are parsing actual JSON where null is a value.
When transforming a Map, in Java, null means "no value" which is similar to undefined in JavaScript. The author of this library made the conscious choice to treat Java null like JavaScript undefined.
Whether or not that was the best choice is a little late for this project as it would be a breaking change for people that have been using this project for 20 or so years.
Whether or not that was the best choice is a little late for this project as it would be a breaking change for people that have been using this project for 20 or so years.
Thi is completely understandable. However, I still believe it could be solved, maybe by using a second parameter indicating to threat nulls as Json nulls... (just an idea).
Regarding...
When transforming a
Map, in Java,nullmeans "no value"
...this is not exactly true: since there's still a key in the Map for that value, and all methods regarding Maps threat that as an explicit <key, null> entry.
Java is a strongly typed language and null does not have a type. A variable assigned null has no value as it's un-typed.
JavaScript is an un-typed/loosely-typed language, so null is an actual value.
This design does not seem internally consistent.
I think it would be reasonable to expect JSONObject.toMap to be the inverse of new JSONObject(Map).
new JSONObject("{k:null}") includes the null-valued entry
new JSONObject("{k:null}").toMap() includes the null-valued entry
new JSONObject(new JSONObject("{k:null}").toMap()) drops the null-valued entry
Closing this issue since no fix was proposed. The inconsistency is noted, but changing current behavior might break existing applications. If anyone disagrees, please post here.