fix add null-check to avoid NPE for issue #1882

This commit is contained in:
yanxutao89 2023-09-23 12:09:21 +08:00 committed by 温绍锦
parent 8940c14fb6
commit 7b58ca42bb
5 changed files with 106 additions and 41 deletions

View File

@ -684,25 +684,27 @@ public class ObjectReaderCreator {
boolean[] flags = null;
int maskCount = 0;
for (int i = 0; i < setterFieldReaders.length; i++) {
FieldReader setterFieldReader = setterFieldReaders[i];
if (fieldReaders.containsKey(setterFieldReader.fieldName)) {
if (flags == null) {
flags = new boolean[setterFieldReaders.length];
}
flags[i] = true;
maskCount++;
}
}
if (maskCount > 0) {
FieldReader[] array = new FieldReader[setterFieldReaders.length - maskCount];
int index = 0;
if (setterFieldReaders != null) {
for (int i = 0; i < setterFieldReaders.length; i++) {
if (!flags[i]) {
array[index++] = setterFieldReaders[i];
FieldReader setterFieldReader = setterFieldReaders[i];
if (fieldReaders.containsKey(setterFieldReader.fieldName)) {
if (flags == null) {
flags = new boolean[setterFieldReaders.length];
}
flags[i] = true;
maskCount++;
}
}
setterFieldReaders = array;
if (maskCount > 0) {
FieldReader[] array = new FieldReader[setterFieldReaders.length - maskCount];
int index = 0;
for (int i = 0; i < setterFieldReaders.length; i++) {
if (!flags[i]) {
array[index++] = setterFieldReaders[i];
}
}
setterFieldReaders = array;
}
}
return (ObjectReader<T>) new ObjectReaderNoneDefaultConstructor(

View File

@ -341,6 +341,15 @@ final class ObjectReaderException<T>
return (T) object;
}
@Override
public T createInstance(Map map, long features) {
if (map == null) {
return null;
}
return readObject(JSONReader.of(JSON.toJSONString(map)), features);
}
@Override
public T readJSONBObject(JSONReader jsonReader, Type fieldType, Object fieldName, long features) {
if (jsonReader.getType() == JSONB.Constants.BC_TYPED_ANY) {

View File

@ -471,29 +471,31 @@ public class ObjectReaderNoneDefaultConstructor<T>
: valueMap
);
for (int i = 0; i < setterFieldReaders.length; i++) {
FieldReader fieldReader = setterFieldReaders[i];
Object fieldValue = map.get(fieldReader.fieldName);
if (fieldValue == null) {
continue;
}
Class<?> valueClass = fieldValue.getClass();
Class fieldClass = fieldReader.fieldClass;
Type fieldType = fieldReader.fieldType;
if (!(fieldType instanceof Class)) {
fieldValue = TypeUtils.cast(fieldValue, fieldType, provider);
} else if (valueClass != fieldClass) {
Function typeConvert = provider.getTypeConvert(valueClass, fieldClass);
if (typeConvert != null) {
fieldValue = typeConvert.apply(fieldValue);
} else if (fieldValue instanceof Map) {
ObjectReader objectReader = fieldReader.getObjectReader(JSONFactory.createReadContext(provider));
fieldValue = objectReader.createInstance((Map) fieldValue, features | fieldReader.features);
if (setterFieldReaders != null) {
for (int i = 0; i < setterFieldReaders.length; i++) {
FieldReader fieldReader = setterFieldReaders[i];
Object fieldValue = map.get(fieldReader.fieldName);
if (fieldValue == null) {
continue;
}
}
fieldReader.accept(object, fieldValue);
Class<?> valueClass = fieldValue.getClass();
Class fieldClass = fieldReader.fieldClass;
Type fieldType = fieldReader.fieldType;
if (!(fieldType instanceof Class)) {
fieldValue = TypeUtils.cast(fieldValue, fieldType, provider);
} else if (valueClass != fieldClass) {
Function typeConvert = provider.getTypeConvert(valueClass, fieldClass);
if (typeConvert != null) {
fieldValue = typeConvert.apply(fieldValue);
} else if (fieldValue instanceof Map) {
ObjectReader objectReader = fieldReader.getObjectReader(JSONFactory.createReadContext(provider));
fieldValue = objectReader.createInstance((Map) fieldValue, features | fieldReader.features);
}
}
fieldReader.accept(object, fieldValue);
}
}
return object;

View File

@ -0,0 +1,54 @@
package com.alibaba.fastjson2.issues_1800;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class Issue1822 {
private static String JSON_STRING;
private static MyObj MY_OBJ;
@BeforeAll
public static void init() {
MY_OBJ = new MyObj();
MY_OBJ.setThrowable(new Throwable("测试"));
JSON_STRING = JSON.toJSONString(MY_OBJ);
}
@Test
void testWithError() {
JSONObject jsonObject = JSONObject.parseObject(JSON_STRING);
MyObj myObj = jsonObject.toJavaObject(MyObj.class);
assertEquals(JSON_STRING, JSON.toJSONString(myObj));
assertEquals(MY_OBJ.toString(), myObj.toString());
}
@Test
void testWithoutError() {
MyObj myObj = JSONObject.parseObject(JSON_STRING, MyObj.class);
assertEquals(JSON_STRING, JSON.toJSONString(myObj));
assertEquals(MY_OBJ.toString(), myObj.toString());
}
private static class MyObj {
private Throwable throwable;
public Throwable getThrowable() {
return throwable;
}
public void setThrowable(Throwable throwable) {
this.throwable = throwable;
}
@Override
public String toString() {
return "MyObj{" +
"throwable=" + throwable +
'}';
}
}
}

View File

@ -6,6 +6,7 @@ import java.io.IOException;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class SafeModeTest {
@Test
@ -27,9 +28,6 @@ public class SafeModeTest {
Throwable e1 = JSON.parseObject(jsonString, Throwable.class);
assertEquals(Throwable.class, e1.getClass());
JSONObject object = JSON.parseObject(jsonString);
assertThrows(
Exception.class,
() -> object.toJavaObject(Throwable.class)
);
assertEquals(Throwable.class, object.toJavaObject(Throwable.class).getClass());
}
}