ConvertFactory增加nullable配置

This commit is contained in:
redkale
2023-07-29 09:20:13 +08:00
parent e20d398a73
commit b84006d8db
24 changed files with 436 additions and 130 deletions

View File

@@ -60,7 +60,9 @@ public final class ApiDocCommand {
if (params != null && params.length > 0) {
for (String param : params) {
if (param == null) continue;
if (param == null) {
continue;
}
param = param.toLowerCase();
if (param.startsWith("--api-skiprpc=")) {
skipRPC = "true".equalsIgnoreCase(param.substring("--api-skiprpc=".length()));
@@ -80,7 +82,9 @@ public final class ApiDocCommand {
List<Map> swaggerTags = new ArrayList<>();
Map<String, Map<String, Object>> swaggerComponentsMap = new LinkedHashMap<>();
for (NodeServer node : app.servers) {
if (!(node instanceof NodeHttpServer)) continue;
if (!(node instanceof NodeHttpServer)) {
continue;
}
final Map<String, Object> map = new LinkedHashMap<>();
serverList.add(map);
HttpServer server = node.getServer();
@@ -89,12 +93,20 @@ public final class ApiDocCommand {
List<Map<String, Object>> servletsList = new ArrayList<>();
map.put("servlets", servletsList);
String plainContentType = server.getResponseConfig() == null ? "application/json" : server.getResponseConfig().plainContentType;
if (plainContentType == null || plainContentType.isEmpty()) plainContentType = "application/json";
if (plainContentType.indexOf(';') > 0) plainContentType = plainContentType.substring(0, plainContentType.indexOf(';'));
if (plainContentType == null || plainContentType.isEmpty()) {
plainContentType = "application/json";
}
if (plainContentType.indexOf(';') > 0) {
plainContentType = plainContentType.substring(0, plainContentType.indexOf(';'));
}
for (HttpServlet servlet : server.getDispatcherServlet().getServlets()) {
if (!(servlet instanceof HttpServlet)) continue;
if (servlet instanceof WebSocketServlet) continue;
if (!(servlet instanceof HttpServlet)) {
continue;
}
if (servlet instanceof WebSocketServlet) {
continue;
}
if (servlet.getClass().getAnnotation(MessageMultiConsumer.class) != null) {
node.logger.log(Level.INFO, servlet + " be skipped because has @MessageMultiConsumer");
continue;
@@ -128,16 +140,29 @@ public final class ApiDocCommand {
Class clz = servlet.getClass();
HashSet<String> actionUrls = new HashSet<>();
do {
if (Modifier.isAbstract(clz.getModifiers())) break;
if (Modifier.isAbstract(clz.getModifiers())) {
break;
}
for (Method method : clz.getMethods()) {
if (method.getParameterCount() != 2) continue;
if (method.getParameterCount() != 2) {
continue;
}
HttpMapping action = method.getAnnotation(HttpMapping.class);
if (action == null) continue;
if (!action.inherited() && selfClz != clz) continue; //忽略不被继承的方法
if (actionUrls.contains(action.url())) continue;
if (HttpScope.class.isAssignableFrom(action.result())) continue; //忽略模板引擎的方法
if (action.rpconly() && skipRPC) continue; //不生成RPC接口
if (action == null) {
continue;
}
if (!action.inherited() && selfClz != clz) {
continue; //忽略不被继承的方法
}
if (actionUrls.contains(action.url())) {
continue;
}
if (HttpScope.class.isAssignableFrom(action.result())) {
continue; //忽略模板引擎的方法
}
if (action.rpconly() && skipRPC) {
continue; //不生成RPC接口
}
final List<Map<String, Object>> swaggerParamsList = new ArrayList<>();
final Map<String, Object> mappingMap = new LinkedHashMap<>();
@@ -241,20 +266,36 @@ public final class ApiDocCommand {
swaggerParamsList.add(swaggerParamMap);
}
}
if (param.style() == HttpParam.HttpParameterStyle.BODY) hasbodyparam = true;
if (ptype.isPrimitive() || ptype == String.class) continue;
if (typesMap.containsKey(ptype.getName())) continue;
if (ptype.getName().startsWith("java.")) continue;
if (ptype.getName().startsWith("javax.")) continue;
if (param.style() == HttpParam.HttpParameterStyle.BODY) {
hasbodyparam = true;
}
if (ptype.isPrimitive() || ptype == String.class) {
continue;
}
if (typesMap.containsKey(ptype.getName())) {
continue;
}
if (ptype.getName().startsWith("java.")) {
continue;
}
if (ptype.getName().startsWith("javax.")) {
continue;
}
final Map<String, Map<String, Object>> typeMap = new LinkedHashMap<>();
Class loop = ptype;
final boolean filter = FilterBean.class.isAssignableFrom(loop);
do {
if (loop == null || loop.isInterface()) break;
if (loop == null || loop.isInterface()) {
break;
}
for (Field field : loop.getDeclaredFields()) {
if (Modifier.isFinal(field.getModifiers())) continue;
if (Modifier.isStatic(field.getModifiers())) continue;
if (Modifier.isFinal(field.getModifiers())) {
continue;
}
if (Modifier.isStatic(field.getModifiers())) {
continue;
}
Map<String, Object> fieldmap = new LinkedHashMap<>();
fieldmap.put("type", field.getType().isArray() ? (field.getType().getComponentType().getName() + "[]") : field.getGenericType().getTypeName());
@@ -276,7 +317,9 @@ public final class ApiDocCommand {
fieldmap.put("updatable", (filter || col == null || col.updatable()));
if (servlet.getClass().getAnnotation(Rest.RestDyn.class) != null) {
if (field.getAnnotation(RestAddress.class) != null) continue;
if (field.getAnnotation(RestAddress.class) != null) {
continue;
}
}
typeMap.put(field.getName(), fieldmap);
@@ -301,11 +344,17 @@ public final class ApiDocCommand {
Map<String, Object> respMap = new LinkedHashMap<>();
respMap.put("schema", respSchemaMap);
Object example = formatExample(returnFactory, action.example(), action.result(), resultType);
if (example != null) respSchemaMap.put("example", example);
if (!swaggerRequestBody.isEmpty()) swaggerOperatMap.put("requestBody", swaggerRequestBody);
if (example != null) {
respSchemaMap.put("example", example);
}
if (!swaggerRequestBody.isEmpty()) {
swaggerOperatMap.put("requestBody", swaggerRequestBody);
}
swaggerOperatMap.put("parameters", swaggerParamsList);
String actiondesc = action.comment();
if (action.rpconly()) actiondesc = "[Only for RPC API] " + actiondesc;
if (action.rpconly()) {
actiondesc = "[Only for RPC API] " + actiondesc;
}
swaggerOperatMap.put("responses", Utility.ofMap("200", Utility.ofMap("description", actiondesc, "content", Utility.ofMap("application/json", respMap))));
String m = action.methods() == null || action.methods().length == 0 ? null : action.methods()[0].toLowerCase();
@@ -319,7 +368,9 @@ public final class ApiDocCommand {
} while ((clz = clz.getSuperclass()) != HttpServlet.class);
mappingsList.sort((o1, o2) -> ((String) o1.get("url")).compareTo((String) o2.get("url")));
servletsList.add(servletMap);
if (!actionUrls.isEmpty()) swaggerTags.add(Utility.ofMap("name", tag, "description", ws.comment()));
if (!actionUrls.isEmpty()) {
swaggerTags.add(Utility.ofMap("name", tag, "description", ws.comment()));
}
}
servletsList.sort((o1, o2) -> {
String[] urlregs1 = (String[]) o1.get("urlregs");
@@ -337,7 +388,9 @@ public final class ApiDocCommand {
swaggerResultMap.put("servers", swaggerServers);
swaggerResultMap.put("paths", swaggerPathsMap);
swaggerResultMap.put("tags", swaggerTags);
if (!swaggerComponentsMap.isEmpty()) swaggerResultMap.put("components", Utility.ofMap("schemas", swaggerComponentsMap));
if (!swaggerComponentsMap.isEmpty()) {
swaggerResultMap.put("components", Utility.ofMap("schemas", swaggerComponentsMap));
}
final FileOutputStream out = new FileOutputStream(new File(app.getHome(), "openapi-doc.json"));
out.write(JsonConvert.root().convertTo(swaggerResultMap).getBytes(StandardCharsets.UTF_8));
out.close();
@@ -421,8 +474,12 @@ public final class ApiDocCommand {
Set<Type> types = new HashSet<>();
Encodeable encodeable = JsonFactory.root().loadEncoder(genericType);
String ct = componentKey(factory, logger, types, componentsMap, null, encodeable, true);
if (ct == null || ct.length() == 0) return null;
if (componentsMap.containsKey(ct)) return ct;
if (ct == null || ct.length() == 0) {
return null;
}
if (componentsMap.containsKey(ct)) {
return ct;
}
Map<String, Object> cmap = new LinkedHashMap<>();
componentsMap.put(ct, cmap); //必须在调用simpleSchemaType之前put不然嵌套情况下死循环
@@ -440,11 +497,15 @@ public final class ApiDocCommand {
FilterColumn fcol = member.getField().getAnnotation(FilterColumn.class);
if (fcol != null) {
desc = fcol.comment();
if (fcol.required()) requireds.add(member.getAttribute().field());
if (fcol.required()) {
requireds.add(member.getAttribute().field());
}
}
} else {
desc = col.comment();
if (!col.nullable()) requireds.add(member.getAttribute().field());
if (!col.nullable()) {
requireds.add(member.getAttribute().field());
}
}
if (desc.isEmpty() && member.getField().getAnnotation(Comment.class) != null) {
desc = member.getField().getAnnotation(Comment.class).value();
@@ -457,11 +518,15 @@ public final class ApiDocCommand {
FilterColumn fcol = member.getMethod().getAnnotation(FilterColumn.class);
if (fcol != null) {
desc = fcol.comment();
if (fcol.required()) requireds.add(member.getAttribute().field());
if (fcol.required()) {
requireds.add(member.getAttribute().field());
}
}
} else {
desc = col.comment();
if (!col.nullable()) requireds.add(member.getAttribute().field());
if (!col.nullable()) {
requireds.add(member.getAttribute().field());
}
}
if (desc.isEmpty() && member.getMethod().getAnnotation(Comment.class) != null) {
desc = member.getMethod().getAnnotation(Comment.class).value();
@@ -469,11 +534,15 @@ public final class ApiDocCommand {
desc = member.getMethod().getAnnotation(org.redkale.util.Comment.class).value();
}
}
if (!desc.isEmpty()) schemaMap.put("description", desc);
if (!desc.isEmpty()) {
schemaMap.put("description", desc);
}
properties.put(member.getAttribute().field(), schemaMap);
}
}
if (!requireds.isEmpty()) cmap.put("required", requireds);
if (!requireds.isEmpty()) {
cmap.put("required", requireds);
}
cmap.put("properties", properties);
return ct;
} catch (Exception e) {
@@ -484,7 +553,9 @@ public final class ApiDocCommand {
private static String componentKey(JsonFactory factory, Logger logger, Set<Type> types, Map<String, Map<String, Object>> componentsMap, EnMember field, Encodeable encodeable, boolean first) {
if (encodeable instanceof ObjectEncoder) {
if (types.contains(encodeable.getType())) return "";
if (types.contains(encodeable.getType())) {
return "";
}
types.add(encodeable.getType());
StringBuilder sb = new StringBuilder();
sb.append(((ObjectEncoder) encodeable).getTypeClass().getSimpleName());
@@ -492,19 +563,33 @@ public final class ApiDocCommand {
if (member.getEncoder() instanceof ArrayEncoder
|| member.getEncoder() instanceof CollectionEncoder) {
String subsb = componentKey(factory, logger, types, componentsMap, member, member.getEncoder(), false);
if (subsb == null) return null;
if (subsb == null) {
return null;
}
AccessibleObject real = member.getField() == null ? member.getMethod() : member.getField();
if (real == null) continue;
if (real == null) {
continue;
}
Class cz = real instanceof Field ? ((Field) real).getType() : ((Method) real).getReturnType();
Type ct = real instanceof Field ? ((Field) real).getGenericType() : ((Method) real).getGenericReturnType();
if (cz == ct) continue;
if (field == null && encodeable.getType() instanceof Class) continue;
if (sb.length() > 0 && subsb.length() > 0) sb.append("_");
if (cz == ct) {
continue;
}
if (field == null && encodeable.getType() instanceof Class) {
continue;
}
if (sb.length() > 0 && subsb.length() > 0) {
sb.append("_");
}
sb.append(subsb);
} else if (member.getEncoder() instanceof ObjectEncoder || member.getEncoder() instanceof SimpledCoder) {
AccessibleObject real = member.getField() == null ? member.getMethod() : member.getField();
if (real == null) continue;
if (types.contains(member.getEncoder().getType())) continue;
if (real == null) {
continue;
}
if (types.contains(member.getEncoder().getType())) {
continue;
}
types.add(member.getEncoder().getType());
if (member.getEncoder() instanceof SimpledCoder) {
simpleSchemaType(factory, logger, componentsMap, ((SimpledCoder) member.getEncoder()).getType(), ((SimpledCoder) member.getEncoder()).getType(), new LinkedHashMap<>(), true);
@@ -513,11 +598,19 @@ public final class ApiDocCommand {
}
Class cz = real instanceof Field ? ((Field) real).getType() : ((Method) real).getReturnType();
Type ct = real instanceof Field ? ((Field) real).getGenericType() : ((Method) real).getGenericReturnType();
if (cz == ct) continue;
if (cz == ct) {
continue;
}
String subsb = componentKey(factory, logger, types, componentsMap, member, member.getEncoder(), false);
if (subsb == null) return null;
if (field == null && member.getEncoder().getType() instanceof Class) continue;
if (sb.length() > 0 && subsb.length() > 0) sb.append("_");
if (subsb == null) {
return null;
}
if (field == null && member.getEncoder().getType() instanceof Class) {
continue;
}
if (sb.length() > 0 && subsb.length() > 0) {
sb.append("_");
}
sb.append(subsb);
} else if (member.getEncoder() instanceof MapEncoder) {
continue;
@@ -529,9 +622,13 @@ public final class ApiDocCommand {
} else if (encodeable instanceof ArrayEncoder || encodeable instanceof CollectionEncoder) {
final boolean array = (encodeable instanceof ArrayEncoder);
Encodeable subEncodeable = array ? ((ArrayEncoder) encodeable).getComponentEncoder() : ((CollectionEncoder) encodeable).getComponentEncoder();
if (subEncodeable instanceof SimpledCoder && field != null) return "";
if (subEncodeable instanceof SimpledCoder && field != null) {
return "";
}
final String sb = componentKey(factory, logger, types, componentsMap, null, subEncodeable, false);
if (sb == null || sb.isEmpty()) return sb;
if (sb == null || sb.isEmpty()) {
return sb;
}
if (field != null && field.getField() != null && field.getField().getDeclaringClass() == Sheet.class) {
return sb;
}
@@ -550,7 +647,9 @@ public final class ApiDocCommand {
}
private static Object formatExample(JsonFactory factory, String example, Class type, Type genericType) {
if (example != null && !example.isEmpty()) return example;
if (example != null && !example.isEmpty()) {
return example;
}
JsonFactory jsonFactory = factory == null || factory == JsonFactory.root() ? exampleFactory : factory;
if (type == Flipper.class) {
return new Flipper();
@@ -642,8 +741,12 @@ public final class ApiDocCommand {
json.append("{");
int index = 0;
for (DeMember member : ((ObjectDecoder) decoder).getMembers()) {
if (!(member.getDecoder() instanceof ObjectDecoder)) continue;
if (index > 0) json.append(",");
if (!(member.getDecoder() instanceof ObjectDecoder)) {
continue;
}
if (index > 0) {
json.append(",");
}
json.append('"').append(member.getAttribute().field()).append("\":{}");
index++;
}
@@ -659,6 +762,6 @@ public final class ApiDocCommand {
return example;
}
private static final JsonFactory exampleFactory = JsonFactory.create().tiny(false);
private static final JsonFactory exampleFactory = JsonFactory.create().tiny(false).nullable(false);
}

View File

@@ -24,21 +24,42 @@ import static java.lang.annotation.RetentionPolicy.*;
public @interface ConvertCoder {
/**
* 需要指定的字段类型,指定了coder字段值则可以不设置此字段
* 需要指定的字段类型,类型必须是原字段类型的子类。
* 例如: <br>
* <blockquote><pre>
* &#64;ConvertCoder(column = String.class)
* private CharSequence name;
* </pre></blockquote>
*
* 通常此字段值与encoder/decoder是二选一指定了coder字段值则可以不设置此字段。
*
* @return 字段类名
*/
Class column() default Object.class;
/**
* 序列化定制化的 Encodeable
* 序列化定制化的 Encodeable, 构造函数的参数可以是:<br>
* 1、ConvertFactory
* 2、Type
* 3、Class
* 4、ConvertFactory和Type
* 5、ConvertFactory和Class
*
* 类如果存在instance单实例对象字段值则优先使用instance对象
*
* @return Encodeable 类
*/
Class<? extends Encodeable> encoder() default Encodeable.class;
/**
* 反序列化定制化的 Decodeable
* 反序列化定制化的 Decodeable, 构造函数的参数可以是:<br>
* 1、ConvertFactory
* 2、Type
* 3、Class
* 4、ConvertFactory和Type
* 5、ConvertFactory和Class
*
* 类如果存在instance单实例对象字段值则优先使用instance对象
*
* @return Decodeable 类
*/

View File

@@ -44,7 +44,9 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
protected Convert<R, W> convert;
protected boolean tiny; //String类型值为""Boolean类型值为false时是否需要输出, 默认为false
protected boolean tiny; //值为true时 String类型值为""Boolean类型值为false时不会输出默认为false
protected boolean nullable; ///值为true时 字段值为null时会输出默认为false
private final Encodeable<W, ?> anyEncoder = new AnyEncoder(this);
@@ -72,8 +74,9 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
private boolean skipAllIgnore = false;
protected ConvertFactory(ConvertFactory<R, W> parent, boolean tiny) {
protected ConvertFactory(ConvertFactory<R, W> parent, boolean tiny, boolean nullable) {
this.tiny = tiny;
this.nullable = nullable;
this.parent = parent;
if (parent == null) {
//---------------------------------------------------------
@@ -251,7 +254,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
public abstract ConvertFactory createChild();
public abstract ConvertFactory createChild(boolean tiny);
public abstract ConvertFactory createChild(boolean tiny, boolean nullable);
protected SimpledCoder createEnumSimpledCoder(Class enumClass) {
return new EnumSimpledCoder(this, enumClass);
@@ -335,6 +338,11 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
return this;
}
public ConvertFactory nullable(boolean nullable) {
this.nullable = nullable;
return this;
}
public boolean isConvertDisabled(AccessibleObject element) {
ConvertDisabled[] ccs = element.getAnnotationsByType(ConvertDisabled.class);
if (ccs.length == 0 && element instanceof Method) {
@@ -630,7 +638,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
}
}
ConvertFactory columnFactory(Class type, ConvertCoder[] coders, boolean encode) {
ConvertFactory columnFactory(Type type, ConvertCoder[] coders, boolean encode) {
if (coders == null || coders.length < 1) {
return this;
}
@@ -642,7 +650,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
if (!ann.type().contains(ct)) {
continue;
}
Class colType = type;
Type colType = type;
if (ann.column() != Object.class) {
colType = ann.column();
}
@@ -679,7 +687,9 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
if (paramTypes.length == 0) {
encoder = creator.create();
} else if (paramTypes.length == 1) {
if (Type.class.isAssignableFrom(paramTypes[0])) {
if (Class.class.isAssignableFrom(paramTypes[0])) {
encoder = creator.create((Object) TypeToken.typeToClass(colType));
} else if (Type.class.isAssignableFrom(paramTypes[0])) {
encoder = creator.create((Object) colType);
} else if (ConvertFactory.class.isAssignableFrom(paramTypes[0])) {
encoder = creator.create(this);
@@ -687,7 +697,11 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
throw new ConvertException(enClazz + " not found public empty-parameter Constructor");
}
} else if (paramTypes.length == 2) {
if (ConvertFactory.class.isAssignableFrom(paramTypes[0]) && Type.class.isAssignableFrom(paramTypes[1])) {
if (ConvertFactory.class.isAssignableFrom(paramTypes[0]) && Class.class.isAssignableFrom(paramTypes[1])) {
encoder = creator.create(this, TypeToken.typeToClass(colType));
} else if (Class.class.isAssignableFrom(paramTypes[0]) && ConvertFactory.class.isAssignableFrom(paramTypes[1])) {
encoder = creator.create(TypeToken.typeToClass(colType), this);
} else if (ConvertFactory.class.isAssignableFrom(paramTypes[0]) && Type.class.isAssignableFrom(paramTypes[1])) {
encoder = creator.create(this, colType);
} else if (Type.class.isAssignableFrom(paramTypes[0]) && ConvertFactory.class.isAssignableFrom(paramTypes[1])) {
encoder = creator.create(colType, this);
@@ -740,7 +754,9 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
if (paramTypes.length == 0) {
decoder = creator.create();
} else if (paramTypes.length == 1) {
if (Type.class.isAssignableFrom(paramTypes[0])) {
if (Class.class.isAssignableFrom(paramTypes[0])) {
decoder = creator.create((Object) TypeToken.typeToClass(colType));
} else if (Type.class.isAssignableFrom(paramTypes[0])) {
decoder = creator.create((Object) colType);
} else if (ConvertFactory.class.isAssignableFrom(paramTypes[0])) {
decoder = creator.create(this);
@@ -748,7 +764,11 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
throw new ConvertException(deClazz + " not found public empty-parameter Constructor");
}
} else if (paramTypes.length == 2) {
if (ConvertFactory.class.isAssignableFrom(paramTypes[0]) && Type.class.isAssignableFrom(paramTypes[1])) {
if (ConvertFactory.class.isAssignableFrom(paramTypes[0]) && Class.class.isAssignableFrom(paramTypes[1])) {
decoder = creator.create(this, TypeToken.typeToClass(colType));
} else if (Class.class.isAssignableFrom(paramTypes[0]) && ConvertFactory.class.isAssignableFrom(paramTypes[1])) {
decoder = creator.create(TypeToken.typeToClass(colType), this);
} else if (ConvertFactory.class.isAssignableFrom(paramTypes[0]) && Type.class.isAssignableFrom(paramTypes[1])) {
decoder = creator.create(this, colType);
} else if (Type.class.isAssignableFrom(paramTypes[0]) && ConvertFactory.class.isAssignableFrom(paramTypes[1])) {
decoder = creator.create(colType, this);

View File

@@ -6,7 +6,7 @@
package org.redkale.convert;
/**
* Convert的扩展实现类加载器
* Convert的扩展实现类加载器, 通过此类可以创建自定义的序列化格式例如protobuf、xmlbean
*
*
* 详情见: https://redkale.org

View File

@@ -5,12 +5,12 @@
*/
package org.redkale.convert;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* 序列化时标记String字段的值是否为无转义字符且长度不超过255的字符串
* 序列化时标记String字段的值是否为无转义字符且长度不超过255的字符串,通常用于类名、字段名、枚举值字符串等
*
* <p>
* 详情见: https://redkale.org

View File

@@ -114,7 +114,7 @@ public class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T> {
continue;
}
ConvertSmallString small = field.getAnnotation(ConvertSmallString.class);
colFactory = factory.columnFactory(field.getType(), field.getAnnotationsByType(ConvertCoder.class), false);
colFactory = factory.columnFactory(field.getGenericType(), field.getAnnotationsByType(ConvertCoder.class), false);
Decodeable<R, ?> fieldCoder;
if (small != null && field.getType() == String.class) {
fieldCoder = StringSimpledCoder.SmallStringSimpledCoder.instance;
@@ -197,9 +197,9 @@ public class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T> {
ConvertSmallString small = method.getAnnotation(ConvertSmallString.class);
Field maybeField = ConvertFactory.readGetSetField(method);
colFactory = factory.columnFactory(method.getParameterTypes()[0], method.getAnnotationsByType(ConvertCoder.class), false);
colFactory = factory.columnFactory(method.getGenericParameterTypes()[0], method.getAnnotationsByType(ConvertCoder.class), false);
if (maybeField != null && colFactory == factory) {
colFactory = factory.columnFactory(maybeField.getType(), maybeField.getAnnotationsByType(ConvertCoder.class), false);
colFactory = factory.columnFactory(maybeField.getGenericType(), maybeField.getAnnotationsByType(ConvertCoder.class), false);
}
Decodeable<R, ?> fieldCoder;
if (small != null && method.getParameterTypes()[0] == String.class) {

View File

@@ -95,7 +95,7 @@ public class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T> {
continue;
}
ConvertSmallString small = field.getAnnotation(ConvertSmallString.class);
colFactory = factory.columnFactory(field.getType(), field.getAnnotationsByType(ConvertCoder.class), true);
colFactory = factory.columnFactory(field.getGenericType(), field.getAnnotationsByType(ConvertCoder.class), true);
Encodeable<W, ?> fieldCoder;
if (small != null && field.getType() == String.class) {
fieldCoder = StringSimpledCoder.SmallStringSimpledCoder.instance;
@@ -165,9 +165,9 @@ public class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T> {
}
}
Field maybeField = ConvertFactory.readGetSetField(method);
colFactory = factory.columnFactory(method.getReturnType(), method.getAnnotationsByType(ConvertCoder.class), true);
colFactory = factory.columnFactory(method.getGenericReturnType(), method.getAnnotationsByType(ConvertCoder.class), true);
if (maybeField != null && colFactory == factory) {
colFactory = factory.columnFactory(maybeField.getType(), maybeField.getAnnotationsByType(ConvertCoder.class), true);
colFactory = factory.columnFactory(maybeField.getGenericType(), maybeField.getAnnotationsByType(ConvertCoder.class), true);
}
Encodeable<W, ?> fieldCoder;
if (small != null && method.getReturnType() == String.class) {

View File

@@ -74,6 +74,13 @@ public abstract class Writer {
*/
public abstract boolean tiny();
/**
* 当nullable=true时 字段值为null时会输出该字段
*
* @return 是否简化
*/
public abstract boolean nullable();
/**
* 输出null值
*/
@@ -132,6 +139,12 @@ public abstract class Writer {
value = objFieldFunc.apply(member.attribute, obj);
}
if (value == null) {
if (nullable()) {
Attribute attr = member.getAttribute();
this.writeFieldName(member, attr.field(), attr.genericType(), member.getPosition());
writeNull();
this.comma = true;
}
return;
}
if (tiny()) {
@@ -164,6 +177,11 @@ public abstract class Writer {
@SuppressWarnings("unchecked")
public void writeObjectField(final String fieldName, Type fieldType, int fieldPos, Encodeable anyEncoder, Object value) {
if (value == null) {
if (nullable()) {
this.writeFieldName(null, fieldName, fieldType, fieldPos);
writeNull();
this.comma = true;
}
return;
}
if (fieldType == null) {

View File

@@ -26,12 +26,13 @@ public class BsonByteBufferWriter extends BsonWriter {
private int index;
public BsonByteBufferWriter(Supplier<ByteBuffer> supplier) {
this(false, supplier);
this(false, false, supplier);
}
protected BsonByteBufferWriter(boolean tiny, Supplier<ByteBuffer> supplier) {
protected BsonByteBufferWriter(boolean tiny, boolean nullable, Supplier<ByteBuffer> supplier) {
super((byte[]) null);
this.tiny = tiny;
this.nullable = nullable;
this.supplier = supplier;
}
@@ -76,6 +77,12 @@ public class BsonByteBufferWriter extends BsonWriter {
return this;
}
@Override
public BsonByteBufferWriter nullable(boolean nullable) {
this.nullable = nullable;
return this;
}
@Override
protected int expand(final int byteLength) {
if (this.buffers == null) {

View File

@@ -48,9 +48,12 @@ public class BsonConvert extends BinaryConvert<BsonReader, BsonWriter> {
private final boolean tiny;
protected BsonConvert(ConvertFactory<BsonReader, BsonWriter> factory, boolean tiny) {
private final boolean nullable;
protected BsonConvert(ConvertFactory<BsonReader, BsonWriter> factory, boolean tiny, boolean nullable) {
super(factory);
this.tiny = tiny;
this.nullable = nullable;
}
@Override
@@ -79,7 +82,7 @@ public class BsonConvert extends BinaryConvert<BsonReader, BsonWriter> {
@Override
public BsonConvert newConvert(final BiFunction<Attribute, Object, Object> fieldFunc, BiFunction<Object, Object, Object> mapFieldFunc, Function<Object, ConvertField[]> objExtFunc) {
return new BsonConvert(getFactory(), tiny) {
return new BsonConvert(getFactory(), tiny, nullable) {
@Override
protected <S extends BsonWriter> S configWrite(S writer) {
return fieldFunc(writer, fieldFunc, mapFieldFunc, objExtFunc);
@@ -117,11 +120,11 @@ public class BsonConvert extends BinaryConvert<BsonReader, BsonWriter> {
//------------------------------ writer -----------------------------------------------------------
public BsonByteBufferWriter pollWriter(final Supplier<ByteBuffer> supplier) {
return configWrite(new BsonByteBufferWriter(tiny, supplier));
return configWrite(new BsonByteBufferWriter(tiny, nullable, supplier));
}
protected BsonWriter pollWriter(final OutputStream out) {
return configWrite(new BsonStreamWriter(tiny, out));
return configWrite(new BsonStreamWriter(tiny, nullable, out));
}
@Override
@@ -132,7 +135,7 @@ public class BsonConvert extends BinaryConvert<BsonReader, BsonWriter> {
} else {
writerPool.set(null);
}
return configWrite(writer.tiny(tiny));
return configWrite(writer.tiny(tiny).nullable(nullable));
}
@Override
@@ -237,7 +240,7 @@ public class BsonConvert extends BinaryConvert<BsonReader, BsonWriter> {
@Override
public void convertToBytes(final ByteArray array, final Type type, final Object value) {
Objects.requireNonNull(array);
final BsonWriter writer = configWrite(new BsonWriter(array).tiny(tiny));
final BsonWriter writer = configWrite(new BsonWriter(array).tiny(tiny).nullable(nullable));
if (value == null) {
writer.writeNull();
} else {
@@ -283,7 +286,7 @@ public class BsonConvert extends BinaryConvert<BsonReader, BsonWriter> {
if (value == null) {
return null;
}
final BsonWriter writer = writerPool.get().tiny(tiny);
final BsonWriter writer = writerPool.get().tiny(tiny).nullable(nullable);
factory.loadEncoder(type == null ? value.getClass() : type).convertTo(writer, value);
return writer;
}

View File

@@ -24,7 +24,9 @@ import org.redkale.util.TypeToken;
@SuppressWarnings("unchecked")
public final class BsonFactory extends ConvertFactory<BsonReader, BsonWriter> {
private static final BsonFactory instance = new BsonFactory(null, getSystemPropertyBoolean("redkale.convert.bson.tiny", "redkale.convert.tiny", false));
private static final BsonFactory instance = new BsonFactory(null,
getSystemPropertyBoolean("redkale.convert.bson.tiny", "redkale.convert.tiny", true),
getSystemPropertyBoolean("redkale.convert.bson.nullable", "redkale.convert.nullable", false));
static final Decodeable objectDecoder = instance.loadDecoder(Object.class);
@@ -48,8 +50,8 @@ public final class BsonFactory extends ConvertFactory<BsonReader, BsonWriter> {
//instance.register(AnyValue.class, instance.loadEncoder(AnyValue.DefaultAnyValue.class));
}
private BsonFactory(BsonFactory parent, boolean tiny) {
super(parent, tiny);
private BsonFactory(BsonFactory parent, boolean tiny, boolean nullable) {
super(parent, tiny, nullable);
}
@Override
@@ -62,6 +64,16 @@ public final class BsonFactory extends ConvertFactory<BsonReader, BsonWriter> {
return this.tiny;
}
@Override
public BsonFactory nullable(boolean nullable) {
this.nullable = nullable;
return this;
}
protected boolean nullable() {
return this.nullable;
}
@Override
public BsonFactory skipAllIgnore(final boolean skipIgnore) {
this.registerSkipAllIgnore(skipIgnore);
@@ -73,25 +85,26 @@ public final class BsonFactory extends ConvertFactory<BsonReader, BsonWriter> {
}
public static BsonFactory create() {
return new BsonFactory(null, getSystemPropertyBoolean("redkale.convert.bson.tiny", "redkale.convert.tiny", false));
return new BsonFactory(null, getSystemPropertyBoolean("redkale.convert.bson.tiny", "redkale.convert.tiny", true),
getSystemPropertyBoolean("redkale.convert.bson.nullable", "redkale.convert.nullable", false));
}
@Override
public final BsonConvert getConvert() {
if (convert == null) {
convert = new BsonConvert(this, tiny);
convert = new BsonConvert(this, tiny, nullable);
}
return (BsonConvert) convert;
}
@Override
public BsonFactory createChild() {
return new BsonFactory(this, this.tiny);
return new BsonFactory(this, this.tiny, this.nullable);
}
@Override
public BsonFactory createChild(boolean tiny) {
return new BsonFactory(this, tiny);
public BsonFactory createChild(boolean tiny, boolean nullable) {
return new BsonFactory(this, tiny, nullable);
}
@Override

View File

@@ -18,8 +18,8 @@ class BsonStreamWriter extends BsonByteBufferWriter {
private OutputStream out;
protected BsonStreamWriter(boolean tiny, OutputStream out) {
super(tiny, null);
protected BsonStreamWriter(boolean tiny, boolean nullable, OutputStream out) {
super(tiny, nullable, null);
this.out = out;
}

View File

@@ -29,6 +29,8 @@ public class BsonWriter extends Writer implements ByteTuple {
protected boolean tiny = BsonFactory.root().tiny();
protected boolean nullable = BsonFactory.root().nullable();
public static ObjectPool<BsonWriter> createPool(int max) {
return ObjectPool.createSafePool(max, (Object... params) -> new BsonWriter(), null, (t) -> t.recycle());
}
@@ -105,6 +107,16 @@ public class BsonWriter extends Writer implements ByteTuple {
return this;
}
@Override
public final boolean nullable() {
return nullable;
}
public BsonWriter nullable(boolean nullable) {
this.nullable = nullable;
return this;
}
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
/**

View File

@@ -34,12 +34,13 @@ public class JsonByteBufferWriter extends JsonWriter {
private int index;
public JsonByteBufferWriter(boolean tiny, Supplier<ByteBuffer> supplier) {
this(tiny, null, supplier);
public JsonByteBufferWriter(boolean tiny, boolean nullable, Supplier<ByteBuffer> supplier) {
this(tiny, nullable, null, supplier);
}
public JsonByteBufferWriter(boolean tiny, Charset charset, Supplier<ByteBuffer> supplier) {
public JsonByteBufferWriter(boolean tiny, boolean nullable, Charset charset, Supplier<ByteBuffer> supplier) {
this.tiny = tiny;
this.nullable = nullable;
this.charset = charset;
this.supplier = supplier;
}
@@ -311,6 +312,10 @@ public class JsonByteBufferWriter extends JsonWriter {
*/
@Override
public void writeLatin1To(final boolean quote, final String value) {
if (value == null) {
writeNull();
return;
}
byte[] bs = Utility.latin1ByteArray(value);
int expandsize = expand(bs.length + (quote ? 2 : 0));
if (expandsize == 0) {// 只需要一个buffer
@@ -564,6 +569,12 @@ public class JsonByteBufferWriter extends JsonWriter {
@Override
public void writeLastFieldLatin1Value(final byte[] fieldBytes, final String value) {
if (value == null && nullable()) {
writeTo(fieldBytes);
writeNull();
writeTo('}');
return;
}
if (value == null || (tiny && value.isEmpty())) {
expand(1);
this.buffers[index].put((byte) '}');
@@ -616,6 +627,13 @@ public class JsonByteBufferWriter extends JsonWriter {
@Override //firstFieldBytes 必须带{开头
public void writeObjectByOnlyOneLatin1FieldValue(final byte[] firstFieldBytes, final String value) {
if (value == null && nullable()) {
writeTo('{');
writeTo(firstFieldBytes);
writeNull();
writeTo('}');
return;
}
if (value == null || (tiny && value.isEmpty())) {
int expandsize = expand(2);
if (expandsize == 0) { // 只需要一个buffer

View File

@@ -5,9 +5,9 @@
*/
package org.redkale.convert.json;
import java.lang.reflect.*;
import java.nio.charset.*;
import java.util.function.*;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.function.Consumer;
import org.redkale.convert.*;
import static org.redkale.convert.json.JsonWriter.*;
import org.redkale.util.*;
@@ -55,8 +55,9 @@ public class JsonBytesWriter extends JsonWriter implements ByteTuple {
this.count = array.length();
}
public JsonBytesWriter(boolean tiny, ByteArray array) {
public JsonBytesWriter(boolean tiny, boolean nullable, ByteArray array) {
this.tiny = tiny;
this.nullable = nullable;
this.content = array.content();
this.count = array.length();
}
@@ -158,6 +159,10 @@ public class JsonBytesWriter extends JsonWriter implements ByteTuple {
*/
@Override
public void writeLatin1To(final boolean quote, final String value) {
if (value == null) {
writeNull();
return;
}
byte[] bs = Utility.latin1ByteArray(value);
int len = bs.length;
if (quote) {
@@ -271,6 +276,12 @@ public class JsonBytesWriter extends JsonWriter implements ByteTuple {
@Override
public void writeLastFieldLatin1Value(final byte[] fieldBytes, final String value) {
if (value == null && nullable()) {
writeTo(fieldBytes);
writeNull();
writeTo('}');
return;
}
if (value == null || (tiny && value.isEmpty())) {
expand(1);
content[count++] = '}';
@@ -294,6 +305,13 @@ public class JsonBytesWriter extends JsonWriter implements ByteTuple {
@Override //firstFieldBytes 必须带{开头
public void writeObjectByOnlyOneLatin1FieldValue(final byte[] firstFieldBytes, final String value) {
if (value == null && nullable()) {
writeTo('{');
writeTo(firstFieldBytes);
writeNull();
writeTo('}');
return;
}
if (value == null || (tiny && value.isEmpty())) {
expand(2);
content[count++] = '{';

View File

@@ -104,6 +104,10 @@ public class JsonCharsWriter extends JsonWriter {
*/
@Override
public void writeLatin1To(final boolean quote, final String value) {
if (value == null) {
writeNull();
return;
}
int len = value.length();
expand(len + (quote ? 2 : 0));
if (quote) {
@@ -220,6 +224,12 @@ public class JsonCharsWriter extends JsonWriter {
@Override
public void writeLastFieldLatin1Value(final byte[] fieldBytes, final String value) {
if (value == null && nullable()) {
writeTo(fieldBytes);
writeNull();
writeTo('}');
return;
}
if (value == null || (tiny && value.isEmpty())) {
expand(1);
content[count++] = '}';
@@ -241,6 +251,13 @@ public class JsonCharsWriter extends JsonWriter {
@Override //firstFieldBytes 必须带{开头
public void writeObjectByOnlyOneLatin1FieldValue(final byte[] firstFieldBytes, final String value) {
if (value == null && nullable()) {
writeTo('{');
writeTo(firstFieldBytes);
writeNull();
writeTo('}');
return;
}
if (value == null || (tiny && value.isEmpty())) {
expand(2);
content[count++] = '{';

View File

@@ -42,13 +42,16 @@ public class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
private final boolean tiny;
private final boolean nullable;
private Encodeable lastConvertEncodeable;
private Decodeable lastConvertDecodeable;
protected JsonConvert(JsonFactory factory, boolean tiny) {
protected JsonConvert(JsonFactory factory, boolean tiny, boolean nullable) {
super(factory);
this.tiny = tiny;
this.nullable = nullable;
}
@Override
@@ -77,7 +80,7 @@ public class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
@Override
public JsonConvert newConvert(final BiFunction<Attribute, Object, Object> objFieldFunc, BiFunction<Object, Object, Object> mapFieldFunc, Function<Object, ConvertField[]> objExtFunc) {
return new JsonConvert(getFactory(), tiny) {
return new JsonConvert(getFactory(), tiny, nullable) {
@Override
protected <S extends JsonWriter> S configWrite(S writer) {
return fieldFunc(writer, objFieldFunc, mapFieldFunc, objExtFunc);
@@ -112,7 +115,7 @@ public class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
} else {
bytesWriterPool.set(null);
}
return configWrite((JsonBytesWriter) writer.tiny(tiny));
return configWrite((JsonBytesWriter) writer.tiny(tiny).nullable(nullable));
}
@Override
@@ -132,7 +135,7 @@ public class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
} else {
bytesWriterPool.set(null);
}
return configWrite((JsonBytesWriter) writer.tiny(tiny));
return configWrite((JsonBytesWriter) writer.tiny(tiny).nullable(nullable));
}
private void offerJsonBytesWriter(final JsonBytesWriter writer) {
@@ -392,7 +395,7 @@ public class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
@Override
public void convertToBytes(final ByteArray array, final Type type, final Object value) {
Objects.requireNonNull(array);
JsonBytesWriter writer = configWrite(new JsonBytesWriter(tiny, array));
JsonBytesWriter writer = configWrite(new JsonBytesWriter(tiny, nullable, array));
if (value == null) {
writer.writeNull();
} else {
@@ -412,10 +415,10 @@ public class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
public void convertTo(final OutputStream out, final Type type, final Object value) {
if (value == null) {
configWrite(new JsonStreamWriter(tiny, out)).writeNull();
configWrite(new JsonStreamWriter(tiny, nullable, out)).writeNull();
} else {
final Type t = type == null ? value.getClass() : type;
JsonStreamWriter writer = configWrite(new JsonStreamWriter(tiny, out));
JsonStreamWriter writer = configWrite(new JsonStreamWriter(tiny, nullable, out));
Encodeable encoder = this.lastConvertEncodeable;
if (encoder == null || encoder.getType() != t) {
encoder = factory.loadEncoder(t);
@@ -431,7 +434,7 @@ public class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
@Override
public ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Type type, final Object value) {
Objects.requireNonNull(supplier);
JsonByteBufferWriter out = configWrite(new JsonByteBufferWriter(tiny, supplier));
JsonByteBufferWriter out = configWrite(new JsonByteBufferWriter(tiny, nullable, supplier));
if (value == null) {
out.writeNull();
} else {

View File

@@ -386,7 +386,7 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
final Map<String, AccessibleObject> mixedNames = mixedNames0;
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
final String newDynName = "org/redkaledyn/json/_Dyn" + JsonDynEncoder.class.getSimpleName()
+ "__" + clazz.getName().replace('.', '_').replace('$', '_') + "_" + factory.tiny() + "_" + Utility.md5Hex(memberb.toString()); //tiny必须要加上, 同一个类会有多个字段定制Convert
+ "__" + clazz.getName().replace('.', '_').replace('$', '_') + "_" + factory.tiny() + "_" + factory.nullable() + "_" + Utility.md5Hex(memberb.toString()); //tiny必须要加上, 同一个类会有多个字段定制Convert
try {
Class clz = RedkaleClassLoader.findDynClass(newDynName.replace('/', '.'));
Class newClazz = clz == null ? loader.loadClass(newDynName.replace('/', '.')) : clz;
@@ -512,7 +512,7 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
int maxLocals = 4;
int elementIndex = -1;
final Class firstType = readGetSetFieldType(members.get(0));
final boolean mustHadComma = firstType.isPrimitive() && (firstType != boolean.class || !factory.tiny()); //byte/short/char/int/float/long/double
final boolean mustHadComma = firstType.isPrimitive() && (firstType != boolean.class || !factory.tiny() || factory.nullable()); //byte/short/char/int/float/long/double
if (onlyOneLatin1FieldObjectFlag) {
//out.writeObjectByOnlyOneLatin1FieldValue(messageFirstFieldBytes, value.getMessage());elementIndex++;
@@ -670,7 +670,7 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
}
}
Label msgnotemptyif = null;
if (!fieldtype.isPrimitive()) { //if (message != null) { start
if (!fieldtype.isPrimitive() && !factory.nullable()) { //if (message != null) { start
mv.visitVarInsn(loadid, maxLocals);
msgnotemptyif = new Label();
mv.visitJumpInsn(IFNULL, msgnotemptyif);
@@ -794,7 +794,7 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
mv.visitVarInsn(loadid, maxLocals);
mv.visitMethodInsn(INVOKEINTERFACE, encodeableName, "convertTo", "(" + writerDesc + "Ljava/lang/Object;)V", true);
}
if (!fieldtype.isPrimitive()) { //if (message != null) } end
if (!fieldtype.isPrimitive() && !factory.nullable()) { //if (message != null) } end
mv.visitLabel(msgnotemptyif);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
} else if (fieldtype == boolean.class && factory.tiny()) {

View File

@@ -24,7 +24,9 @@ import org.redkale.util.Uint128;
@SuppressWarnings("unchecked")
public final class JsonFactory extends ConvertFactory<JsonReader, JsonWriter> {
private static final JsonFactory instance = new JsonFactory(null, getSystemPropertyBoolean("redkale.convert.json.tiny", "redkale.convert.tiny", false));
private static final JsonFactory instance = new JsonFactory(null,
getSystemPropertyBoolean("redkale.convert.json.tiny", "redkale.convert.tiny", false),
getSystemPropertyBoolean("redkale.convert.json.nullable", "redkale.convert.nullable", false));
static {
instance.register(Serializable.class, instance.loadEncoder(Object.class));
@@ -33,8 +35,8 @@ public final class JsonFactory extends ConvertFactory<JsonReader, JsonWriter> {
//instance.register(AnyValue.class, instance.loadEncoder(AnyValue.DefaultAnyValue.class));
}
private JsonFactory(JsonFactory parent, boolean tiny) {
super(parent, tiny);
private JsonFactory(JsonFactory parent, boolean tiny, boolean nullable) {
super(parent, tiny, nullable);
if (parent == null) {
this.register(InetAddress.class, InetAddressSimpledCoder.InetAddressJsonSimpledCoder.instance);
this.register(InetSocketAddress.class, InetAddressSimpledCoder.InetSocketAddressJsonSimpledCoder.instance);
@@ -59,6 +61,12 @@ public final class JsonFactory extends ConvertFactory<JsonReader, JsonWriter> {
return this;
}
@Override
public JsonFactory nullable(boolean nullable) {
this.nullable = nullable;
return this;
}
@Override
public JsonFactory skipAllIgnore(final boolean skipIgnore) {
this.registerSkipAllIgnore(skipIgnore);
@@ -70,7 +78,8 @@ public final class JsonFactory extends ConvertFactory<JsonReader, JsonWriter> {
}
public static JsonFactory create() {
return new JsonFactory(null, getSystemPropertyBoolean("redkale.convert.json.tiny", "redkale.convert.tiny", false));
return new JsonFactory(null, getSystemPropertyBoolean("redkale.convert.json.tiny", "redkale.convert.tiny", false),
getSystemPropertyBoolean("redkale.convert.json.nullable", "redkale.convert.nullable", false));
}
@Override
@@ -92,22 +101,26 @@ public final class JsonFactory extends ConvertFactory<JsonReader, JsonWriter> {
return this.tiny;
}
protected boolean nullable() {
return this.nullable;
}
@Override
public final JsonConvert getConvert() {
if (convert == null) {
convert = new JsonConvert(this, tiny);
convert = new JsonConvert(this, tiny, nullable);
}
return (JsonConvert) convert;
}
@Override
public JsonFactory createChild() {
return new JsonFactory(this, this.tiny);
return new JsonFactory(this, this.tiny, this.nullable);
}
@Override
public JsonFactory createChild(boolean tiny) {
return new JsonFactory(this, tiny);
public JsonFactory createChild(boolean tiny, boolean nullable) {
return new JsonFactory(this, tiny, nullable);
}
@Override

View File

@@ -21,12 +21,12 @@ class JsonStreamWriter extends JsonByteBufferWriter {
private OutputStream out;
protected JsonStreamWriter(boolean tiny, OutputStream out) {
this(tiny, null, out);
protected JsonStreamWriter(boolean tiny, boolean nullable, OutputStream out) {
this(tiny, nullable, null, out);
}
protected JsonStreamWriter(boolean tiny, Charset charset, OutputStream out) {
super(tiny, charset, null);
protected JsonStreamWriter(boolean tiny, boolean nullable, Charset charset, OutputStream out) {
super(tiny, nullable, charset, null);
this.out = out;
}
@@ -101,6 +101,10 @@ class JsonStreamWriter extends JsonByteBufferWriter {
*/
@Override
public void writeLatin1To(final boolean quote, final String value) {
if (value == null) {
writeNull();
return;
}
char[] chs = Utility.charArray(value);
writeTo(quote, chs, 0, chs.length);
}

View File

@@ -23,6 +23,8 @@ public abstract class JsonWriter extends Writer {
protected boolean tiny = JsonFactory.root().tiny();
protected boolean nullable = JsonFactory.root().nullable();
@Override
public boolean tiny() {
return tiny;
@@ -37,6 +39,16 @@ public abstract class JsonWriter extends Writer {
return this.objExtFunc == null && this.objFieldFunc == null;
}
@Override
public boolean nullable() {
return nullable;
}
public JsonWriter nullable(boolean nullable) {
this.nullable = nullable;
return this;
}
//-----------------------------------------------------------------------
public abstract void writeTo(final char ch); //只能是 0 - 127 的字符

View File

@@ -20,6 +20,19 @@ import org.redkale.util.*;
*/
public class BsonMainTest {
public static void main(String[] args) throws Throwable {
BsonMainTest test = new BsonMainTest();
test.run1();
test.run2();
test.run3();
test.run4();
test.run5();
test.run6();
test.run7();
test.run8();
}
@Test
public void run1() throws Throwable {
Serializable[] sers = new Serializable[]{"aaa", 4};
@@ -38,7 +51,7 @@ public class BsonMainTest {
SimpleChildEntity entry = SimpleChildEntity.create();
byte[] bytes = convert.convertTo(SimpleEntity.class, entry);
System.out.println("长度: " + bytes.length);
Assertions.assertEquals(271, bytes.length);
Assertions.assertEquals(260, bytes.length);
BsonByteBufferWriter writer = convert.pollWriter(() -> ByteBuffer.allocate(1));
convert.convertTo(writer, SimpleEntity.class, entry);
ByteBuffer[] buffers = writer.toBuffers();
@@ -52,7 +65,7 @@ public class BsonMainTest {
b.flip();
}
System.out.println("长度: " + len);
Assertions.assertEquals(271, len);
Assertions.assertEquals(260, len);
SimpleChildEntity entry2 = convert.convertFrom(SimpleChildEntity.class, buffers);
System.out.println(entry);
Assertions.assertEquals(entry.toString(), entry2.toString());

View File

@@ -17,11 +17,21 @@ public class Json5Test {
public static void main(String[] args) throws Throwable {
Json5Test test = new Json5Test();
test.main = true;
test.run();
test.run1();
test.run2();
}
@Test
public void run() throws Exception {
public void run1() throws Exception {
JsonFactory factory = JsonFactory.root().tiny(true).nullable(true);
final JsonConvert convert = factory.getConvert();
Json5Bean bean = new Json5Bean();
bean.id = 60;
System.out.println(convert.convertTo(bean));
}
@Test
public void run2() throws Exception {
JsonConvert convert = JsonConvert.root();
Json5Bean bean = new Json5Bean();
bean.id = 500;

View File

@@ -37,6 +37,7 @@ public class JsonMainTest {
String json = "{\"access_token\":\"null\",\"priv\":null, vvv:nulla,\"priv2\":\"nulla\",\"expires_in\":7200, \"aa\":\"\"}";
Map<String, String> map = convert.convertFrom(JsonConvert.TYPE_MAP_STRING_STRING, json);
System.out.println(map);
System.out.println(map.get("priv") == null);
String rs = convert.convertTo(map);
System.out.println(rs);
ByteBuffer[] buffers = convert.convertTo(() -> ByteBuffer.allocate(1024), map);
@@ -52,7 +53,7 @@ public class JsonMainTest {
SimpleChildEntity entry = SimpleChildEntity.create();
String json = convert.convertTo(SimpleEntity.class, entry);
System.out.println("长度: " + json.length());
JsonByteBufferWriter writer = new JsonByteBufferWriter(false, () -> ByteBuffer.allocate(1)) {
JsonByteBufferWriter writer = new JsonByteBufferWriter(false, false, () -> ByteBuffer.allocate(1)) {
};
convert.convertTo(writer, SimpleEntity.class, entry);
ByteBuffer[] buffers = writer.toBuffers();