mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
add methods
This commit is contained in:
parent
64a04fdfd1
commit
463d8d9c6f
@ -117,7 +117,7 @@ public final class InternalJSONUtil {
|
||||
.setIgnoreError(config.isIgnoreError())
|
||||
.setIgnoreNullValue(config.isIgnoreNullValue())
|
||||
.setTransientSupport(config.isTransientSupport())
|
||||
.setConverter((targetType, value) -> mapper.toJSON(value));
|
||||
.setConverter((targetType, value) -> mapper.toJSON(value, false));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -120,7 +120,8 @@ public class JSONArray extends ListWrapper<JSON> implements JSON, JSONGetter<Int
|
||||
* @return this.
|
||||
*/
|
||||
public JSONArray addObj(final Object value) {
|
||||
this.add(this.factory.getMapper().toJSON(value));
|
||||
// add时,如果value为字符串,不解析,而是作为JSONPrimitive对待
|
||||
this.add(this.factory.getMapper().toJSON(value, false));
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -171,7 +172,8 @@ public class JSONArray extends ListWrapper<JSON> implements JSON, JSONGetter<Int
|
||||
* @return this
|
||||
*/
|
||||
public JSONArray setObj(final int index, final Object element) {
|
||||
set(index, this.factory.getMapper().toJSON(element));
|
||||
// set时,如果value为字符串,不解析,而是作为JSONPrimitive对待
|
||||
set(index, this.factory.getMapper().toJSON(element, false));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -267,7 +267,12 @@ public class JSONFactory {
|
||||
// region ----- parse
|
||||
|
||||
/**
|
||||
* 对象转JSONObject对象
|
||||
* 对象转{@link JSONObject},支持:
|
||||
* <ul>
|
||||
* <li>{@link CharSequence},解析{...}字符串</li>
|
||||
* <li>Bean解析</li>
|
||||
* <li>Map解析</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param obj Bean对象或者Map
|
||||
* @return JSONObject
|
||||
@ -292,23 +297,37 @@ public class JSONFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换对象为JSON,如果用户不配置JSONConfig,则JSON的有序与否与传入对象有关。<br>
|
||||
* 解析对象为JSON<br>
|
||||
* 支持的对象:
|
||||
* <ul>
|
||||
* <li>String: 转换为相应的对象</li>
|
||||
* <li>Array、Iterable、Iterator:转换为JSONArray</li>
|
||||
* <li>Bean对象:转为JSONObject</li>
|
||||
* </ul>
|
||||
* 注意:与{@link #toJSON(Object)}不同的是,对象如果为字符串,会被当作json字符串解析!
|
||||
*
|
||||
* @param obj 对象
|
||||
* @return JSON(JSONObject or JSONArray)
|
||||
*/
|
||||
public JSON parse(final Object obj) {
|
||||
final JSONMapper mapper = this.getMapper();
|
||||
if (obj instanceof CharSequence) {
|
||||
return mapper.toJSON((CharSequence) obj);
|
||||
return getMapper().toJSON(obj, true);
|
||||
}
|
||||
return mapper.toJSON(obj);
|
||||
|
||||
/**
|
||||
* 转换对象为JSON<br>
|
||||
* 支持的对象:
|
||||
* <ul>
|
||||
* <li>String: 转换为{@link JSONPrimitive}</li>
|
||||
* <li>Array、Iterable、Iterator:转换为JSONArray</li>
|
||||
* <li>Bean对象:转为JSONObject</li>
|
||||
* </ul>
|
||||
* 注意;与{@link #parse(Object)}不同的是,对象如果为字符串,则返回{@link JSONPrimitive},不会做二次解析
|
||||
*
|
||||
* @param obj 对象
|
||||
* @return JSON(JSONObject or JSONArray)
|
||||
*/
|
||||
public JSON toJSON(final Object obj) {
|
||||
return getMapper().toJSON(obj, false);
|
||||
}
|
||||
// endregion
|
||||
|
||||
|
@ -233,7 +233,8 @@ public class JSONObject extends MapWrapper<String, JSON> implements JSON, JSONGe
|
||||
* @throws JSONException 值是无穷数字抛出此异常
|
||||
*/
|
||||
public JSONObject putObj(final String key, final Object value) throws JSONException {
|
||||
this.put(key, factory.getMapper().toJSON(value));
|
||||
// put时,如果value为字符串,不解析,而是作为JSONPrimitive对待
|
||||
this.put(key, factory.getMapper().toJSON(value, false));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -195,12 +195,12 @@ public class JSONUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换对象为JSON,如果用户不配置JSONConfig,则JSON的有序与否与传入对象有关。<br>
|
||||
* 支持的对象:
|
||||
* 解析对象为JSON,持的对象:
|
||||
* <ul>
|
||||
* <li>String: 转换为相应的对象</li>
|
||||
* <li>Array、Iterable、Iterator:转换为JSONArray</li>
|
||||
* <li>Bean对象:转为JSONObject</li>
|
||||
* <li>String: 解析为相应的对象</li>
|
||||
* <li>Number、boolean: 转换为{@link JSONPrimitive}</li>
|
||||
* <li>Array、Iterable、Iterator:转换为{@link JSONArray}</li>
|
||||
* <li>Bean对象:转为{@link JSONObject}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param obj 对象
|
||||
@ -211,45 +211,46 @@ public class JSONUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换对象为JSON,如果用户不配置JSONConfig,则JSON的有序与否与传入对象有关。<br>
|
||||
* 支持的对象:
|
||||
* 解析对象为JSON,持的对象:
|
||||
* <ul>
|
||||
* <li>String: 转换为相应的对象</li>
|
||||
* <li>Array、Iterable、Iterator:转换为JSONArray</li>
|
||||
* <li>Bean对象:转为JSONObject</li>
|
||||
* <li>String: 解析为相应的对象</li>
|
||||
* <li>Number、boolean: 转换为{@link JSONPrimitive}</li>
|
||||
* <li>Array、Iterable、Iterator:转换为{@link JSONArray}</li>
|
||||
* <li>Bean对象:转为{@link JSONObject}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param obj 对象
|
||||
* @param config JSON配置,{@code null}使用默认配置
|
||||
* @return JSON(JSONObject or JSONArray)
|
||||
* @return JSON
|
||||
*/
|
||||
public static JSON parse(final Object obj, final JSONConfig config) {
|
||||
return parse(obj, config, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换对象为JSON,如果用户不配置JSONConfig,则JSON的有序与否与传入对象有关。<br>
|
||||
* 支持的对象:
|
||||
* 解析对象为JSON,持的对象:
|
||||
* <ul>
|
||||
* <li>String: 转换为相应的对象</li>
|
||||
* <li>Array、Iterable、Iterator:转换为JSONArray</li>
|
||||
* <li>Bean对象:转为JSONObject</li>
|
||||
* <li>String: 解析为相应的对象</li>
|
||||
* <li>Number、boolean: 转换为{@link JSONPrimitive}</li>
|
||||
* <li>Array、Iterable、Iterator:转换为{@link JSONArray}</li>
|
||||
* <li>Bean对象:转为{@link JSONObject}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param obj 对象
|
||||
* @param config JSON配置,{@code null}使用默认配置
|
||||
* @param predicate 键值对过滤编辑器,可以通过实现此接口,完成解析前对键值对的过滤和修改操作,{@link Predicate#test(Object)}为{@code true}保留
|
||||
* @return JSON(JSONObject or JSONArray)
|
||||
* @param predicate 键值对过滤编辑器,可以通过实现此接口,完成解析前对键值对的过滤和修改操作,
|
||||
* {@link Predicate#test(Object)}为{@code true}保留
|
||||
* @return JSON
|
||||
*/
|
||||
public static JSON parse(final Object obj, final JSONConfig config, final Predicate<MutableEntry<Object, Object>> predicate) {
|
||||
return JSONFactory.of(config, predicate).parse(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* XML字符串转为JSONObject
|
||||
* XML字符串解析为{@link JSONObject}
|
||||
*
|
||||
* @param xmlStr XML字符串
|
||||
* @return JSONObject
|
||||
* @return {@link JSONObject}
|
||||
*/
|
||||
public static JSONObject parseFromXml(final String xmlStr) {
|
||||
return JSONXMLUtil.toJSONObject(xmlStr);
|
||||
@ -418,7 +419,62 @@ public class JSONUtil {
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region ----- toJSON
|
||||
|
||||
/**
|
||||
* 转换对象为JSON,如果用户不配置JSONConfig,则JSON的有序与否与传入对象有关。<br>
|
||||
* 支持的对象:
|
||||
* <ul>
|
||||
* <li>boolean、Number、String: 转换为{@link JSONPrimitive}/li>
|
||||
* <li>Array、Iterable、Iterator:转换为{@link JSONArray}</li>
|
||||
* <li>Bean对象:转为{@link JSONObject}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param obj 对象
|
||||
* @return JSON
|
||||
*/
|
||||
public static JSON toJSON(final Object obj) {
|
||||
return JSONFactory.getInstance().toJSON(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换对象为JSON,如果用户不配置JSONConfig,则JSON的有序与否与传入对象有关。<br>
|
||||
* 支持的对象:
|
||||
* <ul>
|
||||
* <li>boolean、Number、String: 转换为{@link JSONPrimitive}</li>
|
||||
* <li>Array、Iterable、Iterator:转换为{@link JSONArray}</li>
|
||||
* <li>Bean对象:转为{@link JSONObject}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param obj 对象
|
||||
* @param config JSON配置,{@code null}使用默认配置
|
||||
* @return JSON
|
||||
*/
|
||||
public static JSON toJSON(final Object obj, final JSONConfig config) {
|
||||
return toJSON(obj, config, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换对象为JSON,如果用户不配置JSONConfig,则JSON的有序与否与传入对象有关。<br>
|
||||
* 支持的对象:
|
||||
* <ul>
|
||||
* <li>boolean、Number、String: 转换为{@link JSONPrimitive}</li>
|
||||
* <li>Array、Iterable、Iterator:转换为{@link JSONArray}</li>
|
||||
* <li>Bean对象:转为{@link JSONObject}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param obj 对象
|
||||
* @param config JSON配置,{@code null}使用默认配置
|
||||
* @param predicate 键值对过滤编辑器,可以通过实现此接口,完成解析前对键值对的过滤和修改操作,{@link Predicate#test(Object)}为{@code true}保留
|
||||
* @return JSON
|
||||
*/
|
||||
public static JSON toJSON(final Object obj, final JSONConfig config, final Predicate<MutableEntry<Object, Object>> predicate) {
|
||||
return JSONFactory.of(config, predicate).toJSON(obj);
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region ----- toList
|
||||
|
||||
/**
|
||||
* 将JSONArray字符串转换为Bean的List,默认为ArrayList
|
||||
*
|
||||
@ -601,6 +657,7 @@ public class JSONUtil {
|
||||
}
|
||||
|
||||
// region ----- isType
|
||||
|
||||
/**
|
||||
* 是否为JSON类型字符串,首尾都为大括号或中括号判定为JSON字符串
|
||||
*
|
||||
@ -642,6 +699,7 @@ public class JSONUtil {
|
||||
// endregion
|
||||
|
||||
// region ----- registerTypeAdapter
|
||||
|
||||
/**
|
||||
* 全局注册自定义类型适配器,用于自定义对象序列化和反序列化
|
||||
*
|
||||
|
@ -20,6 +20,7 @@ import org.dromara.hutool.core.lang.Opt;
|
||||
import org.dromara.hutool.core.reflect.TypeReference;
|
||||
import org.dromara.hutool.core.util.ObjUtil;
|
||||
import org.dromara.hutool.json.*;
|
||||
import org.dromara.hutool.json.serializer.impl.CharSequenceTypeAdapter;
|
||||
import org.dromara.hutool.json.serializer.impl.DefaultDeserializer;
|
||||
|
||||
import java.io.Serializable;
|
||||
@ -29,7 +30,7 @@ import java.util.Optional;
|
||||
/**
|
||||
* 对象和JSON值映射器,用于Java对象和JSON对象互转<br>
|
||||
* <ul>
|
||||
* <li>Java对象转JSON:{@link #toJSON(Object)}</li>
|
||||
* <li>Java对象转JSON:{@link #toJSON(Object, boolean)}</li>
|
||||
* <li>JSON转Java对象:{@link #toBean(JSON, Type)}</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
@ -139,22 +140,23 @@ public class JSONMapper implements Serializable {
|
||||
}
|
||||
|
||||
// region ----- toJSON
|
||||
|
||||
/**
|
||||
* 在需要的时候转换映射对象<br>
|
||||
* 包装包括:
|
||||
* <ul>
|
||||
* <li>array or collection =》 JSONArray</li>
|
||||
* <li>map =》 JSONObject</li>
|
||||
* <li>standard property (Double, String, et al) =》 原对象</li>
|
||||
* <li>array or collection =》 {@link JSONArray}</li>
|
||||
* <li>map or bean =》 {@link JSONObject}</li>
|
||||
* <li>standard property (number boolean or char) =》 {@link JSONPrimitive}</li>
|
||||
* <li>String =》 parseIfString为{@code true}时解析为{@link JSON},{@code false}直接包装为{@link JSONPrimitive}</li>
|
||||
* <li>其它 =》 尝试包装为JSONObject,否则返回{@code null}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param obj 被映射的对象
|
||||
* @param parseIfString 如果提供的是字符串,是否解析为JSON,{@code false}则直接包装为{@link JSONPrimitive}
|
||||
* @return 映射后的值,null表示此值需被忽略
|
||||
*/
|
||||
public JSON toJSON(final Object obj) {
|
||||
return mapTo(obj, null);
|
||||
public JSON toJSON(final Object obj, final boolean parseIfString) {
|
||||
return mapTo(obj, null, parseIfString);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -169,7 +171,7 @@ public class JSONMapper implements Serializable {
|
||||
* @return 映射后的值,null表示此值需被忽略
|
||||
*/
|
||||
public JSONObject toJSONObject(final Object obj) {
|
||||
return mapTo(obj, factory.ofObj());
|
||||
return mapTo(obj, factory.ofObj(), false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -183,7 +185,7 @@ public class JSONMapper implements Serializable {
|
||||
* @return 映射后的值,null表示此值需被忽略
|
||||
*/
|
||||
public JSONArray toJSONArray(final Object obj) {
|
||||
return mapTo(obj, factory.ofArray());
|
||||
return mapTo(obj, factory.ofArray(), false);
|
||||
}
|
||||
// endregion
|
||||
|
||||
@ -191,19 +193,22 @@ public class JSONMapper implements Serializable {
|
||||
* 在需要的时候转换映射对象<br>
|
||||
* 包装包括:
|
||||
* <ul>
|
||||
* <li>array or collection =》 JSONArray</li>
|
||||
* <li>map =》 JSONObject</li>
|
||||
* <li>standard property (Double, String, et al) =》 原对象</li>
|
||||
* <li>array or collection =》 {@link JSONArray}</li>
|
||||
* <li>map or bean =》 {@link JSONObject}</li>
|
||||
* <li>standard property (number boolean or char) =》 {@link JSONPrimitive}</li>
|
||||
* <li>String =》 parseIfString为{@code true}时解析为{@link JSON},{@code false}直接包装为{@link JSONPrimitive}</li>
|
||||
* <li>其它 =》 尝试包装为JSONObject,否则返回{@code null}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param obj 被映射的对象
|
||||
* @param json 被映射的到的对象,{@code null}表示根据序列化器自动识别
|
||||
* @param parseIfString 如果提供的是字符串,是否解析为JSON,{@code false}则直接包装为{@link JSONPrimitive},
|
||||
* 只有json参数为{@code null}时有效
|
||||
* @param <T> JSON类型
|
||||
* @return 映射后的值,null表示此值需被忽略
|
||||
*/
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private <T extends JSON> T mapTo(Object obj, final T json) {
|
||||
private <T extends JSON> T mapTo(Object obj, final T json, final boolean parseIfString) {
|
||||
if (null == obj) {
|
||||
return null;
|
||||
}
|
||||
@ -224,9 +229,19 @@ public class JSONMapper implements Serializable {
|
||||
// 考虑性能问题,默认原始类型对象直接包装为JSONPrimitive,不再查找TypeAdapter
|
||||
// 如果原始类型想转为其他JSON类型,依旧可以查找TypeAdapter
|
||||
if (JSONPrimitive.isTypeForJSONPrimitive(obj)) {
|
||||
if (null == json || json instanceof JSONPrimitive) {
|
||||
if (null == json) {
|
||||
// 未指定转换的JSON类型,对于String产生二义性
|
||||
// 通过parseIfString参数决定是解析字符串还是直接转为原始类型
|
||||
if (parseIfString && obj instanceof String) {
|
||||
return (T) CharSequenceTypeAdapter.INSTANCE.serialize((String)obj,
|
||||
new SimpleJSONContext(null, factory));
|
||||
}
|
||||
return (T) factory.ofPrimitive(obj);
|
||||
}
|
||||
if (json instanceof JSONPrimitive) {
|
||||
return (T) factory.ofPrimitive(obj);
|
||||
}
|
||||
// 用户想将Primitive对象转为特定JSON对象,则需要查找TypeAdapter
|
||||
}
|
||||
|
||||
// JSON对象如果与预期结果类型一致,则直接返回
|
||||
|
@ -19,7 +19,6 @@ package org.dromara.hutool.json.serializer.impl;
|
||||
import org.dromara.hutool.core.reflect.TypeUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.json.JSON;
|
||||
import org.dromara.hutool.json.JSONFactory;
|
||||
import org.dromara.hutool.json.JSONObject;
|
||||
import org.dromara.hutool.json.JSONPrimitive;
|
||||
import org.dromara.hutool.json.reader.JSONTokener;
|
||||
@ -86,7 +85,7 @@ public class CharSequenceTypeAdapter implements MatcherJSONSerializer<CharSequen
|
||||
}
|
||||
|
||||
// 按照JSON字符串解析
|
||||
return parse(new JSONTokener(jsonStr), context.getFactory());
|
||||
return context.getFactory().ofParser(new JSONTokener(jsonStr)).parse();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -96,15 +95,4 @@ public class CharSequenceTypeAdapter implements MatcherJSONSerializer<CharSequen
|
||||
}
|
||||
return json.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 从{@link JSONTokener} 中读取JSON字符串,并解析为JSON
|
||||
*
|
||||
* @param tokener {@link JSONTokener}
|
||||
* @param factory JSON工厂
|
||||
* @return JSON
|
||||
*/
|
||||
public static JSON parse(final JSONTokener tokener, final JSONFactory factory) {
|
||||
return factory.ofParser(tokener).parse();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class JSONFactoryTest {
|
||||
@Test
|
||||
void parseFromStringBuilderTest() {
|
||||
final String jsonStr = "{\"name\":\"张三\"}";
|
||||
final JSON parse = JSONFactory.getInstance().parse(new StringBuilder(jsonStr));
|
||||
Assertions.assertEquals(JSONObject.class, parse.getClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
void parseFromStringTest() {
|
||||
final String jsonStr = "{\"name\":\"张三\"}";
|
||||
final JSON parse = JSONFactory.getInstance().parse(jsonStr);
|
||||
Assertions.assertEquals(JSONObject.class, parse.getClass());
|
||||
}
|
||||
}
|
@ -31,7 +31,7 @@ public class Issue3681Test {
|
||||
Assertions.assertEquals("\"abc\"", abc);
|
||||
|
||||
abc = JSONUtil.toJsonStr(Optional.of("123"));
|
||||
Assertions.assertEquals("\"123\"", abc);
|
||||
Assertions.assertEquals("123", abc);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -46,6 +46,7 @@ public class Issue3681Test {
|
||||
Assertions.assertEquals("\"abc\"", abc);
|
||||
|
||||
abc = JSONUtil.toJsonStr(Opt.of("123"));
|
||||
Assertions.assertEquals("\"123\"", abc);
|
||||
Assertions.assertEquals("123", abc);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ public class IssueI9DX5HTest {
|
||||
entry.setKey(StrUtil.toUnderlineCase((CharSequence) entry.getKey()));
|
||||
return true;
|
||||
});
|
||||
final JSONObject jsonObject = (JSONObject) factory.parse(xml);
|
||||
final JSONObject jsonObject = factory.parseObj(xml);
|
||||
|
||||
Assertions.assertEquals("{\"good_msg\":\"你好\"}", jsonObject.toString());
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user