Allow to configure Java null handling.

This commit is contained in:
Robert Lichtenberger 2025-03-19 07:59:57 +01:00
parent 6452a6f38d
commit d1327c2da3
3 changed files with 72 additions and 1 deletions

View File

@ -332,7 +332,7 @@ public class JSONObject {
throw new NullPointerException("Null key.");
}
final Object value = e.getValue();
if (value != null) {
if (value != null || jsonParserConfiguration.isJavaNullAsJsonNull()) {
testValidity(value);
this.map.put(String.valueOf(e.getKey()), wrap(value, recursionDepth + 1, jsonParserConfiguration));
}

View File

@ -8,6 +8,11 @@ public class JSONParserConfiguration extends ParserConfiguration {
* Used to indicate whether to overwrite duplicate key or not.
*/
private boolean overwriteDuplicateKey;
/**
* Used to indicate whether ignore null values when converting java maps to JSONObject or not.
*/
private boolean javaNullAsJsonNull;
/**
* Configuration with the default values.
@ -67,6 +72,21 @@ public class JSONParserConfiguration extends ParserConfiguration {
return clone;
}
/**
* Controls the parser's behavior when meeting duplicate keys.
* If set to false, the parser will throw a JSONException when meeting a duplicate key.
* Or the duplicate key's value will be overwritten.
*
* @param javaNullAsJsonNull define, if the parser should ignore null values in Java maps
* @return The existing configuration will not be modified. A new configuration is returned.
*/
public JSONParserConfiguration withJavaNullAsJsonNull(final boolean javaNullAsJsonNull) {
JSONParserConfiguration clone = this.clone();
clone.javaNullAsJsonNull = javaNullAsJsonNull;
return clone;
}
/**
* Sets the strict mode configuration for the JSON parser with default true value
@ -106,6 +126,17 @@ public class JSONParserConfiguration extends ParserConfiguration {
public boolean isOverwriteDuplicateKey() {
return this.overwriteDuplicateKey;
}
/**
* The parser's behavior when meeting a null value in a java map, controls whether the parser should ignore
* that map entry or write a JSON entry with a null value.
*
* @return The <code>javaNullAsJsonNull</code> configuration value.
*/
public boolean isJavaNullAsJsonNull() {
return this.javaNullAsJsonNull;
}
/**
* The parser throws an Exception when strict mode is true and tries to parse invalid JSON characters.

View File

@ -616,6 +616,46 @@ public class JSONObjectTest {
assertTrue("expected \"doubleKey\":-23.45e67", Double.valueOf("-23.45e67").equals(jsonObject.query("/doubleKey")));
Util.checkJSONObjectMaps(jsonObject);
}
@Test
public void jsonObjectByMapWithNullValueAndParserConfiguration() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("nullKey", null);
// by default, null values are ignored
JSONObject obj1 = new JSONObject(map);
assertTrue("expected null value to be ignored by default", obj1.isEmpty());
// if configured, null values are written as such into the JSONObject.
JSONParserConfiguration parserConfiguration = new JSONParserConfiguration().withJavaNullAsJsonNull(true);
JSONObject obj2 = new JSONObject(map, parserConfiguration);
assertFalse("expected null value to accepted when configured", obj2.isEmpty());
assertTrue(obj2.has("nullKey"));
assertEquals(JSONObject.NULL, obj2.get("nullKey"));
}
@Test
public void jsonObjectByMapWithNestedNullValueAndParserConfiguration() {
Map<String, Object> map = new HashMap<String, Object>();
Map<String, Object> nestedMap = new HashMap<String, Object>();
nestedMap.put("nullKey", null);
map.put("nestedMap", nestedMap);
List<Map<String, Object>> nestedList = new ArrayList<Map<String,Object>>();
nestedList.add(nestedMap);
map.put("nestedList", nestedList);
JSONParserConfiguration parserConfiguration = new JSONParserConfiguration().withJavaNullAsJsonNull(true);
JSONObject jsonObject = new JSONObject(map, parserConfiguration);
JSONObject nestedObject = jsonObject.getJSONObject("nestedMap");
assertTrue(nestedObject.has("nullKey"));
assertEquals(JSONObject.NULL, nestedObject.get("nullKey"));
JSONArray nestedArray = jsonObject.getJSONArray("nestedList");
assertEquals(1, nestedArray.length());
assertTrue(nestedArray.getJSONObject(0).has("nullKey"));
assertEquals(JSONObject.NULL, nestedArray.getJSONObject(0).get("nullKey"));
}
/**
* JSONObject built from a bean. In this case all but one of the