JSONFactory

This commit is contained in:
Looly 2024-09-26 13:44:12 +08:00
parent 0a36707d48
commit c9eb040b70
7 changed files with 260 additions and 39 deletions

View File

@ -20,6 +20,7 @@ import org.dromara.hutool.core.collection.ListUtil;
import org.dromara.hutool.core.net.url.UrlQuery;
import org.dromara.hutool.core.util.CharsetUtil;
import org.dromara.hutool.json.JSONObject;
import org.dromara.hutool.json.JSONUtil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@ -30,7 +31,7 @@ public class IssueIAFKWPTest {
@Test
void urlWithFormTest() {
final JSONObject obj = new JSONObject();
final JSONObject obj = JSONUtil.ofObj();
obj.set("fields", ListUtil.of("1", "2", "good"));
final Map<String, Object> params = new HashMap<>();

View File

@ -0,0 +1,180 @@
/*
* Copyright (c) 2024 Hutool Team and hutool.cn
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dromara.hutool.json;
import org.dromara.hutool.core.lang.mutable.MutableEntry;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.json.serializer.JSONMapper;
import java.io.ByteArrayInputStream;
import java.lang.reflect.Type;
import java.util.function.Predicate;
/**
* JSON工厂类用于JSON创建解析转换为Bean等功能
*
* @author looly
* @since 6.0.0
*/
public class JSONFactory {
/**
* 创建JSON工厂
*
* @param config JSON配置
* @param predicate 键值对过滤器{@code null}表示不过滤
* @return JSON工厂
*/
public static JSONFactory of(final JSONConfig config, final Predicate<MutableEntry<Object, Object>> predicate) {
return new JSONFactory(config, predicate);
}
private final JSONConfig config;
private final Predicate<MutableEntry<Object, Object>> predicate;
private final JSONMapper mapper;
/**
* 构造
*
* @param config 配置项
* @param predicate 键值对过滤器用于过滤掉不需要的键值对例如过滤掉值为null的键值对
*/
public JSONFactory(final JSONConfig config, final Predicate<MutableEntry<Object, Object>> predicate) {
this.config = ObjUtil.defaultIfNull(config, JSONConfig::of);
this.predicate = predicate;
this.mapper = JSONMapper.of(config, predicate);
}
/**
* 获取{@link JSONMapper}
*
* @return {@link JSONMapper}
*/
public JSONMapper getMapper() {
return mapper;
}
// region ----- of
/**
* 创建JSONObject
*
* @return JSONObject
*/
public JSONObject ofObj() {
return new JSONObject(this.config);
}
/**
* 创建JSONArray
*
* @return JSONArray
*/
public JSONArray ofArray() {
return new JSONArray(this.config);
}
/**
* 创建JSONPrimitive
*
* @param value
* @return JSONPrimitive
*/
public JSONPrimitive ofPrimitive(final Object value) {
return new JSONPrimitive(value, this.config);
}
// endregion
// region ----- parse
/**
* JSON字符串转JSONObject对象
*
* @param obj Bean对象或者Map
* @return JSONObject
*/
public JSONObject parseObj(Object obj) {
if (obj instanceof byte[]) {
obj = new ByteArrayInputStream((byte[]) obj);
}
final JSONMapper jsonMapper = JSONMapper.of(config, predicate);
if (obj instanceof CharSequence) {
return (JSONObject) jsonMapper.map((CharSequence) obj);
}
return jsonMapper.mapObj(obj);
}
/**
* 对象转{@link JSONArray}支持
* <ul>
* <li>{@link JSONObject} 遍历Entry结果为[{k1:v1}, {k2: v2}, ...]</li>
* <li>{@link CharSequence}解析[...]字符串</li>
* <li>其它支持和自定义的对象如集合数组等</li>
* </ul>
*
* @param obj 数组或集合对象
* @return JSONArray
*/
public JSONArray parseArray(final Object obj) {
if (obj instanceof JSONObject) {
final JSONMapper jsonMapper = JSONMapper.of(config, predicate);
return jsonMapper.mapFromJSONObject((JSONObject) obj);
}
final JSONMapper jsonMapper = JSONMapper.of(config, predicate);
if (obj instanceof CharSequence) {
return (JSONArray) jsonMapper.map((CharSequence) obj);
}
return jsonMapper.mapArray(obj);
}
/**
* 转换对象为JSON如果用户不配置JSONConfig则JSON的有序与否与传入对象有关<br>
* 支持的对象
* <ul>
* <li>String: 转换为相应的对象</li>
* <li>ArrayIterableIterator转换为JSONArray</li>
* <li>Bean对象转为JSONObject</li>
* </ul>
*
* @param obj 对象
* @return JSONJSONObject or JSONArray
*/
public JSON parse(final Object obj) {
if (obj instanceof CharSequence) {
return mapper.map((CharSequence) obj);
}
return mapper.map(obj);
}
// endregion
// region ----- toBean
/**
* 将JSON转换为指定类型的Bean对象
*
* @param json JSON
* @param type Bean类型泛型对象使用{@link org.dromara.hutool.core.reflect.TypeReference}
* @param <T> 泛型类型
* @return Bean对象
*/
public <T> T toBean(final JSON json, final Type type) {
return mapper.toBean(json, type);
}
// endregion
}

View File

@ -23,12 +23,10 @@ import org.dromara.hutool.core.lang.mutable.MutableEntry;
import org.dromara.hutool.core.reflect.TypeReference;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.json.serializer.JSONMapper;
import org.dromara.hutool.json.support.JSONStrFormatter;
import org.dromara.hutool.json.writer.JSONWriter;
import org.dromara.hutool.json.xml.JSONXMLUtil;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.Writer;
import java.lang.reflect.Type;
@ -149,24 +147,15 @@ public class JSONUtil {
}
/**
* JSON字符串转JSONObject对象<br>
* 此方法会忽略空值但是对JSON字符串不影响
* 对象转JSONObject对象
*
* @param obj Bean对象或者Map
* @param config JSON配置
* @param predicate 键值对过滤编辑器可以通过实现此接口完成解析前对键值对的过滤和修改操作{@link Predicate#test(Object)}{@code true}保留
* @return JSONObject
*/
public static JSONObject parseObj(Object obj, final JSONConfig config, final Predicate<MutableEntry<Object, Object>> predicate) {
if (obj instanceof byte[]) {
obj = new ByteArrayInputStream((byte[]) obj);
}
final JSONMapper jsonMapper = JSONMapper.of(config, predicate);
if (obj instanceof CharSequence) {
return (JSONObject) jsonMapper.map((CharSequence) obj);
}
return jsonMapper.mapObj(obj);
public static JSONObject parseObj(final Object obj, final JSONConfig config, final Predicate<MutableEntry<Object, Object>> predicate) {
return JSONFactory.of(config, predicate).parseObj(obj);
}
/**
@ -174,7 +163,6 @@ public class JSONUtil {
*
* @param obj 数组或集合对象或字符串等
* @return JSONArray
* @since 3.0.8
*/
public static JSONArray parseArray(final Object obj) {
return parseArray(obj, null);
@ -193,7 +181,7 @@ public class JSONUtil {
}
/**
* JSON字符串转JSONArray
* 对象转JSONArray
*
* @param obj 数组或集合对象
* @param config JSON配置
@ -202,16 +190,7 @@ public class JSONUtil {
* @since 5.3.1
*/
public static JSONArray parseArray(final Object obj, final JSONConfig config, final Predicate<MutableEntry<Object, Object>> predicate) {
if (obj instanceof JSONObject) {
final JSONMapper jsonMapper = JSONMapper.of(config, predicate);
return jsonMapper.mapFromJSONObject((JSONObject) obj);
}
final JSONMapper jsonMapper = JSONMapper.of(config, predicate);
if (obj instanceof CharSequence) {
return (JSONArray) jsonMapper.map((CharSequence) obj);
}
return jsonMapper.mapArray(obj);
return JSONFactory.of(config, predicate).parseArray(obj);
}
/**
@ -262,11 +241,7 @@ public class JSONUtil {
* @return JSONJSONObject or JSONArray
*/
public static JSON parse(final Object obj, final JSONConfig config, final Predicate<MutableEntry<Object, Object>> predicate) {
final JSONMapper jsonMapper = JSONMapper.of(config, predicate);
if (obj instanceof CharSequence) {
return jsonMapper.map((CharSequence) obj);
}
return jsonMapper.map(obj);
return JSONFactory.of(config, predicate).parse(obj);
}
/**

View File

@ -18,6 +18,7 @@ package org.dromara.hutool.json.serializer;
import org.dromara.hutool.core.lang.Opt;
import org.dromara.hutool.core.lang.mutable.MutableEntry;
import org.dromara.hutool.core.reflect.TypeReference;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.json.*;
@ -104,7 +105,11 @@ public class JSONMapper implements Serializable {
* @return 实体类对象
*/
@SuppressWarnings("unchecked")
public <T> T toBean(final JSON json, final Type type) {
public <T> T toBean(final JSON json, Type type) {
if (type instanceof TypeReference) {
type = ((TypeReference<?>) type).getType();
}
if (null == type || Object.class == type) {
if (json instanceof JSONPrimitive) {
return (T) ((JSONPrimitive) json).getValue();

View File

@ -35,18 +35,17 @@ import java.util.Map;
import java.util.Set;
/**
* JSON序列化和反序列化管理器用于管理JSON序列化器注册和注销自定义序列化器和反序列化器<br>
* JSON适配器序列化和反序列化管理器用于管理JSON序列化器注册和注销自定义序列化器和反序列化器<br>
* 此管理器管理着两种类型的序列化器和反序列化器
* <ul>
* <li>类型精准匹配方式通过Java对象类型匹配只会匹配查找的类型而不匹配子类可以调用{@link #register(Type, TypeAdapter)}注册</li>
* <li>匹配器Matcher方式通过判断序列化和反序列化器中match方法找到自定义的序列化和反序列化器可以调用{@link #register(TypeAdapter)}注册</li>
* </ul>
* <p>
* 管理器的使用分为种方式
* 管理器的使用分为种方式
* <ul>
* <li>全局模式 使用{@link TypeAdapterManager#getInstance()}调用单例全局可用</li>
* <li>实例模式 使用{@link TypeAdapterManager#of()}创建实例局部可用</li>
* <li>自定义模式使用{@code new SerializerManager()}创建实例不加载默认的转换器</li>
* <li>实例模式 使用{@link TypeAdapterManager#of()}创建实例局部可用不加载默认的转换器</li>
* </ul>
*
* @author looly
@ -285,8 +284,9 @@ public class TypeAdapterManager {
private static TypeAdapterManager registerDefault(final TypeAdapterManager manager) {
// 自定义序列化器
manager.register(ResourceBundleSerializer.INSTANCE);
manager.register(ResourceSerializer.INSTANCE);
manager.register(TokenerSerializer.INSTANCE);
manager.register(ResourceBundleSerializer.INSTANCE);
// 自定义反序列化器
manager.register(KBeanDeserializer.INSTANCE);

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2024 Hutool Team and hutool.cn
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dromara.hutool.json.serializer.impl;
import org.dromara.hutool.core.io.resource.Resource;
import org.dromara.hutool.json.JSON;
import org.dromara.hutool.json.JSONConfig;
import org.dromara.hutool.json.reader.JSONParser;
import org.dromara.hutool.json.reader.JSONTokener;
import org.dromara.hutool.json.serializer.JSONContext;
import org.dromara.hutool.json.serializer.MatcherJSONSerializer;
/**
* {@link Resource}序列化器
*
* @author looly
* @since 6.0.0
*/
public class ResourceSerializer implements MatcherJSONSerializer<Resource> {
/**
* 单例
*/
public static final ResourceSerializer INSTANCE = new ResourceSerializer();
@Override
public boolean match(final Object bean, final JSONContext context) {
return bean instanceof Resource;
}
@Override
public JSON serialize(final Resource bean, final JSONContext context) {
return mapFromTokener(new JSONTokener(bean.getStream()), context.config());
}
/**
* {@link JSONTokener} 中读取JSON字符串并转换为JSON
*
* @param tokener {@link JSONTokener}
* @return JSON
*/
private JSON mapFromTokener(final JSONTokener tokener, final JSONConfig config) {
return JSONParser.of(tokener, config).setPredicate(null).parse();
}
}

View File

@ -23,6 +23,7 @@ import org.dromara.hutool.core.xml.XmlConstants;
import org.dromara.hutool.json.InternalJSONUtil;
import org.dromara.hutool.json.JSONException;
import org.dromara.hutool.json.JSONObject;
import org.dromara.hutool.json.JSONUtil;
import java.util.function.Predicate;
@ -156,7 +157,7 @@ public class JSONXMLParser {
} else {
tagName = (String) token;
token = null;
jsonobject = new JSONObject();
jsonobject = JSONUtil.ofObj(context.config());
final boolean keepStrings = parseConfig.isKeepStrings();
for (; ; ) {
if (token == null) {