add JSONBeanParser

This commit is contained in:
Looly 2021-08-08 21:36:37 +08:00
parent a9282b9d7c
commit df726654af
8 changed files with 143 additions and 18 deletions

View File

@ -9,6 +9,7 @@
* 【core 】 MapProxy支持return this的setter方法pr#392@Gitee
* 【core 】 BeeDSFactory移除sqlite事务修复代码新版本BeeCP已修复
* 【core 】 增加compress包扩充Zip操作灵活性
* 【json 】 增加JSONBeanParser
### 🐞Bug修复
* 【core 】 改进NumberChineseFormatter算法补充完整单元测试解决零问题

View File

@ -20,7 +20,7 @@ public class DateRange extends Range<DateTime> {
* @param end 结束日期时间包括
* @param unit 步进单位
*/
public DateRange(Date start, Date end, final DateField unit) {
public DateRange(Date start, Date end, DateField unit) {
this(start, end, unit, 1);
}
@ -32,7 +32,7 @@ public class DateRange extends Range<DateTime> {
* @param unit 步进单位
* @param step 步进数
*/
public DateRange(Date start, Date end, final DateField unit, final int step) {
public DateRange(Date start, Date end, DateField unit, int step) {
this(start, end, unit, step, true, true);
}
@ -46,7 +46,7 @@ public class DateRange extends Range<DateTime> {
* @param isIncludeStart 是否包含开始的时间
* @param isIncludeEnd 是否包含结束的时间
*/
public DateRange(Date start, Date end, final DateField unit, final int step, boolean isIncludeStart, boolean isIncludeEnd) {
public DateRange(Date start, Date end, DateField unit, int step, boolean isIncludeStart, boolean isIncludeEnd) {
super(DateUtil.date(start), DateUtil.date(end), (current, end1, index) -> {
final DateTime dt = DateUtil.date(start).offsetNew(unit, (index + 1) * step);
if (dt.isAfter(end1)) {

View File

@ -0,0 +1,18 @@
package cn.hutool.json;
/**
* 实现此接口的类可以通过实现{@code parse(value)}方法来将JSON中的值解析为此对象的值
*
* @author Looly
* @since 5.7.8
*/
public interface JSONBeanParser<T> {
/**
* value转Bean<br>
* 通过实现此接口将JSON中的值填充到当前对象的字段值中即对象自行实现JSON反序列化逻辑
*
* @param value 被解析的对象类型可能为JSON或者普通StringNumber等
*/
void parse(T value);
}

View File

@ -6,6 +6,7 @@ import cn.hutool.core.convert.Converter;
import cn.hutool.core.convert.ConverterRegistry;
import cn.hutool.core.convert.impl.ArrayConverter;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.TypeUtil;
import cn.hutool.json.serialize.GlobalSerializeMapping;
@ -16,7 +17,7 @@ import java.util.List;
/**
* JSON转换器
*
*
* @author looly
* @since 4.2.2
*/
@ -32,7 +33,7 @@ public class JSONConverter implements Converter<JSON> {
/**
* JSONArray转数组
*
*
* @param jsonArray JSONArray
* @param arrayClass 数组元素类型
* @return 数组对象
@ -43,7 +44,7 @@ public class JSONConverter implements Converter<JSON> {
/**
* 将JSONArray转换为指定类型的对量列表
*
*
* @param <T> 元素类型
* @param jsonArray JSONArray
* @param elementType 对象元素类型
@ -69,7 +70,21 @@ public class JSONConverter implements Converter<JSON> {
if (JSONUtil.isNull(value)) {
return null;
}
// since 5.7.8增加自定义Bean反序列化接口
if(targetType instanceof Class){
final Class<?> clazz = (Class<?>) targetType;
if (JSONBeanParser.class.isAssignableFrom(clazz)){
@SuppressWarnings("rawtypes")
JSONBeanParser target = (JSONBeanParser) ReflectUtil.newInstanceIfPossible(clazz);
if(null == target){
throw new ConvertException("Can not instance [{}]", targetType);
}
target.parse(value);
return (T) target;
}
}
if(value instanceof JSON) {
final JSONDeserializer<?> deserializer = GlobalSerializeMapping.getDeserializer(targetType);
if(null != deserializer) {
@ -85,7 +100,7 @@ public class JSONConverter implements Converter<JSON> {
// 此处特殊处理认为返回null属于正常情况
return null;
}
throw new ConvertException("Can not convert {} to type {}", value, ObjectUtil.defaultIfNull(TypeUtil.getClass(targetType), targetType));
}

View File

@ -3,7 +3,7 @@ package cn.hutool.json;
/**
* {@code JSONString}接口定义了一个{@code toJSONString()}<br>
* 实现此接口的类可以通过实现{@code toJSONString()}方法来改变转JSON字符串的方式
*
*
* @author Looly
*
*/
@ -11,7 +11,7 @@ public interface JSONString {
/**
* 自定义转JSON字符串的方法
*
*
* @return JSON字符串
*/
String toJSONString();

View File

@ -1,20 +1,33 @@
package cn.hutool.json;
import cn.hutool.core.bean.BeanUtil;
/**
* JSON支持<br>
* 继承此类实现实体类与JSON的相互转换
*
* @author Looly
*
* @author Looly
*/
public class JSONSupport implements JSONString{
public class JSONSupport implements JSONString, JSONBeanParser<JSON> {
/**
* JSON String转Bean
*
* @param jsonString JSON String
*/
public void parse(String jsonString){
new JSONObject(jsonString).toBean(this.getClass());
public void parse(String jsonString) {
parse(new JSONObject(jsonString));
}
/**
* JSON String转Bean
*
* @param json JSON String
*/
@Override
public void parse(JSON json) {
final JSONSupport support = json.toBean(this.getClass());
BeanUtil.copyProperties(support, this);
}
/**
@ -23,7 +36,7 @@ public class JSONSupport implements JSONString{
public JSONObject toJSON() {
return new JSONObject(this);
}
@Override
public String toJSONString() {
return toJSON().toString();
@ -31,7 +44,7 @@ public class JSONSupport implements JSONString{
/**
* 美化的JSON使用回车缩进显示JSON用于打印输出debug
*
*
* @return 美化的JSON
*/
public String toPrettyString() {

View File

@ -0,0 +1,48 @@
package cn.hutool.json;
import cn.hutool.json.serialize.GlobalSerializeMapping;
import cn.hutool.json.serialize.JSONDeserializer;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import org.junit.Assert;
import org.junit.Test;
/**
* 测试自定义反序列化
*/
public class IssuesI44E4HTest {
@Test
public void deserializerTest(){
GlobalSerializeMapping.put(TestDto.class, (JSONDeserializer<TestDto>) json -> {
final TestDto testDto = new TestDto();
testDto.setMd(new AcBizModuleMd("name1", ((JSONObject)json).getStr("md")));
return testDto;
});
String jsonStr = "{\"md\":\"value1\"}";
final TestDto testDto = JSONUtil.toBean(jsonStr, TestDto.class);
Assert.assertEquals("value1", testDto.getMd().getValue());
}
@Getter
@Setter
@AllArgsConstructor
public static class AcBizModuleMd {
private String name;
private String value;
// 值列表
public static final AcBizModuleMd Value1 = new AcBizModuleMd("value1", "name1");
public static final AcBizModuleMd Value2 = new AcBizModuleMd("value2", "name2");
public static final AcBizModuleMd Value3 = new AcBizModuleMd("value3", "name3");
}
@Getter
@Setter
public static class TestDto {
private AcBizModuleMd md;
}
}

View File

@ -0,0 +1,30 @@
package cn.hutool.json;
import lombok.Data;
import org.junit.Assert;
import org.junit.Test;
public class JSONBeanParserTest {
@Test
public void parseTest(){
String jsonStr = "{\"customName\": \"customValue\", \"customAddress\": \"customAddressValue\"}";
final TestBean testBean = JSONUtil.toBean(jsonStr, TestBean.class);
Assert.assertNotNull(testBean);
Assert.assertEquals("customValue", testBean.getName());
Assert.assertEquals("customAddressValue", testBean.getAddress());
}
@Data
static class TestBean implements JSONBeanParser<JSONObject>{
private String name;
private String address;
@Override
public void parse(JSONObject value) {
this.name = value.getStr("customName");
this.address = value.getStr("customAddress");
}
}
}