Skip to content

Commit d1327c2

Browse files
author
Robert Lichtenberger
committed
Allow to configure Java null handling.
1 parent 6452a6f commit d1327c2

File tree

3 files changed

+72
-1
lines changed

3 files changed

+72
-1
lines changed

src/main/java/org/json/JSONObject.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ private JSONObject(Map<?, ?> m, int recursionDepth, JSONParserConfiguration json
332332
throw new NullPointerException("Null key.");
333333
}
334334
final Object value = e.getValue();
335-
if (value != null) {
335+
if (value != null || jsonParserConfiguration.isJavaNullAsJsonNull()) {
336336
testValidity(value);
337337
this.map.put(String.valueOf(e.getKey()), wrap(value, recursionDepth + 1, jsonParserConfiguration));
338338
}

src/main/java/org/json/JSONParserConfiguration.java

+31
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ public class JSONParserConfiguration extends ParserConfiguration {
88
* Used to indicate whether to overwrite duplicate key or not.
99
*/
1010
private boolean overwriteDuplicateKey;
11+
12+
/**
13+
* Used to indicate whether ignore null values when converting java maps to JSONObject or not.
14+
*/
15+
private boolean javaNullAsJsonNull;
1116

1217
/**
1318
* Configuration with the default values.
@@ -67,6 +72,21 @@ public JSONParserConfiguration withOverwriteDuplicateKey(final boolean overwrite
6772

6873
return clone;
6974
}
75+
76+
/**
77+
* Controls the parser's behavior when meeting duplicate keys.
78+
* If set to false, the parser will throw a JSONException when meeting a duplicate key.
79+
* Or the duplicate key's value will be overwritten.
80+
*
81+
* @param javaNullAsJsonNull define, if the parser should ignore null values in Java maps
82+
* @return The existing configuration will not be modified. A new configuration is returned.
83+
*/
84+
public JSONParserConfiguration withJavaNullAsJsonNull(final boolean javaNullAsJsonNull) {
85+
JSONParserConfiguration clone = this.clone();
86+
clone.javaNullAsJsonNull = javaNullAsJsonNull;
87+
88+
return clone;
89+
}
7090

7191
/**
7292
* Sets the strict mode configuration for the JSON parser with default true value
@@ -106,6 +126,17 @@ public JSONParserConfiguration withStrictMode(final boolean mode) {
106126
public boolean isOverwriteDuplicateKey() {
107127
return this.overwriteDuplicateKey;
108128
}
129+
130+
/**
131+
* The parser's behavior when meeting a null value in a java map, controls whether the parser should ignore
132+
* that map entry or write a JSON entry with a null value.
133+
*
134+
* @return The <code>javaNullAsJsonNull</code> configuration value.
135+
*/
136+
public boolean isJavaNullAsJsonNull() {
137+
return this.javaNullAsJsonNull;
138+
}
139+
109140

110141
/**
111142
* The parser throws an Exception when strict mode is true and tries to parse invalid JSON characters.

src/test/java/org/json/junit/JSONObjectTest.java

+40
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,46 @@ public void jsonObjectByMapWithNullValue() {
616616
assertTrue("expected \"doubleKey\":-23.45e67", Double.valueOf("-23.45e67").equals(jsonObject.query("/doubleKey")));
617617
Util.checkJSONObjectMaps(jsonObject);
618618
}
619+
620+
@Test
621+
public void jsonObjectByMapWithNullValueAndParserConfiguration() {
622+
Map<String, Object> map = new HashMap<String, Object>();
623+
map.put("nullKey", null);
624+
625+
// by default, null values are ignored
626+
JSONObject obj1 = new JSONObject(map);
627+
assertTrue("expected null value to be ignored by default", obj1.isEmpty());
628+
629+
// if configured, null values are written as such into the JSONObject.
630+
JSONParserConfiguration parserConfiguration = new JSONParserConfiguration().withJavaNullAsJsonNull(true);
631+
JSONObject obj2 = new JSONObject(map, parserConfiguration);
632+
assertFalse("expected null value to accepted when configured", obj2.isEmpty());
633+
assertTrue(obj2.has("nullKey"));
634+
assertEquals(JSONObject.NULL, obj2.get("nullKey"));
635+
}
636+
637+
@Test
638+
public void jsonObjectByMapWithNestedNullValueAndParserConfiguration() {
639+
Map<String, Object> map = new HashMap<String, Object>();
640+
Map<String, Object> nestedMap = new HashMap<String, Object>();
641+
nestedMap.put("nullKey", null);
642+
map.put("nestedMap", nestedMap);
643+
List<Map<String, Object>> nestedList = new ArrayList<Map<String,Object>>();
644+
nestedList.add(nestedMap);
645+
map.put("nestedList", nestedList);
646+
647+
JSONParserConfiguration parserConfiguration = new JSONParserConfiguration().withJavaNullAsJsonNull(true);
648+
JSONObject jsonObject = new JSONObject(map, parserConfiguration);
649+
650+
JSONObject nestedObject = jsonObject.getJSONObject("nestedMap");
651+
assertTrue(nestedObject.has("nullKey"));
652+
assertEquals(JSONObject.NULL, nestedObject.get("nullKey"));
653+
654+
JSONArray nestedArray = jsonObject.getJSONArray("nestedList");
655+
assertEquals(1, nestedArray.length());
656+
assertTrue(nestedArray.getJSONObject(0).has("nullKey"));
657+
assertEquals(JSONObject.NULL, nestedArray.getJSONObject(0).get("nullKey"));
658+
}
619659

620660
/**
621661
* JSONObject built from a bean. In this case all but one of the

0 commit comments

Comments
 (0)