Skip to content

Commit dadc3e5

Browse files
committed
Use JSONParserConfiguration to decide on serializing null fields into JSONObject stleary#982
1 parent 24fafcf commit dadc3e5

File tree

2 files changed

+29
-6
lines changed

2 files changed

+29
-6
lines changed

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

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -401,12 +401,17 @@ private JSONObject(Map<?, ?> m, int recursionDepth, JSONParserConfiguration json
401401
*/
402402
public JSONObject(Object bean) {
403403
this();
404-
this.populateMap(bean);
404+
this.populateMap(bean, new JSONParserConfiguration());
405+
}
406+
407+
public JSONObject(Object bean, JSONParserConfiguration jsonParserConfiguration) {
408+
this();
409+
this.populateMap(bean, jsonParserConfiguration);
405410
}
406411

407412
private JSONObject(Object bean, Set<Object> objectsRecord) {
408413
this();
409-
this.populateMap(bean, objectsRecord);
414+
this.populateMap(bean, objectsRecord, new JSONParserConfiguration());
410415
}
411416

412417
/**
@@ -1764,11 +1769,11 @@ public String optString(String key, String defaultValue) {
17641769
* @throws JSONException
17651770
* If a getter returned a non-finite number.
17661771
*/
1767-
private void populateMap(Object bean) {
1768-
populateMap(bean, Collections.newSetFromMap(new IdentityHashMap<Object, Boolean>()));
1772+
private void populateMap(Object bean, JSONParserConfiguration jsonParserConfiguration) {
1773+
populateMap(bean, Collections.newSetFromMap(new IdentityHashMap<Object, Boolean>()), jsonParserConfiguration);
17691774
}
17701775

1771-
private void populateMap(Object bean, Set<Object> objectsRecord) {
1776+
private void populateMap(Object bean, Set<Object> objectsRecord, JSONParserConfiguration jsonParserConfiguration) {
17721777
Class<?> klass = bean.getClass();
17731778

17741779
// If klass is a System class then set includeSuperClass to false.
@@ -1788,7 +1793,7 @@ && isValidMethodName(method.getName())) {
17881793
if (key != null && !key.isEmpty()) {
17891794
try {
17901795
final Object result = method.invoke(bean);
1791-
if (result != null) {
1796+
if (result != null || jsonParserConfiguration.isUseNativeNulls()) {
17921797
// check cyclic dependency and throw error if needed
17931798
// the wrap and populateMap combination method is
17941799
// itself DFS recursive

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4011,5 +4011,23 @@ public static HashMap<String, Object> buildNestedMap(int maxDepth) {
40114011
nestedMap.put("t", buildNestedMap(maxDepth - 1));
40124012
return nestedMap;
40134013
}
4014+
40144015

4016+
/**
4017+
* Tests the behavior of the {@link JSONObject} when parsing a bean with null fields
4018+
* using a custom {@link JSONParserConfiguration} that enables the use of native nulls.
4019+
*
4020+
* <p>This test ensures that uninitialized fields in the bean are serialized correctly
4021+
* into the resulting JSON object, and their keys are present in the JSON string output.</p>
4022+
*/
4023+
@Test
4024+
public void jsonObjectParseNullFieldsWithParserConfiguration() {
4025+
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration();
4026+
RecursiveBean bean = new RecursiveBean(null);
4027+
JSONObject jsonObject = new JSONObject(bean, jsonParserConfiguration.withUseNativeNulls(true));
4028+
String textStr = jsonObject.toString();
4029+
assertTrue("name(uninitialized field) should be serialized", textStr.contains("\"name\""));
4030+
assertTrue("ref(uninitialized field) should be serialized", textStr.contains("\"ref\""));
4031+
assertTrue("ref2(uninitialized field) should be serialized", textStr.contains("\"ref2\""));
4032+
}
40154033
}

0 commit comments

Comments
 (0)