convert优化features
This commit is contained in:
39
src/main/java/org/redkale/annotation/Scheduled.java
Normal file
39
src/main/java/org/redkale/annotation/Scheduled.java
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.redkale.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定时任务标记,只能作用于Service的方法上, 功能类似Spring里的Scheduled注解
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
* @since 2.8.0
|
||||||
|
*/
|
||||||
|
@Target({ElementType.METHOD})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface Scheduled {
|
||||||
|
|
||||||
|
String cron() default "";
|
||||||
|
|
||||||
|
String zone() default "";
|
||||||
|
|
||||||
|
long fixedDelay() default -1;
|
||||||
|
|
||||||
|
String fixedDelayString() default "";
|
||||||
|
|
||||||
|
long fixedRate() default -1;
|
||||||
|
|
||||||
|
String fixedRateString() default "";
|
||||||
|
|
||||||
|
long initialDelay() default -1;
|
||||||
|
|
||||||
|
String initialDelayString() default "";
|
||||||
|
|
||||||
|
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
|
||||||
|
}
|
||||||
@@ -338,7 +338,7 @@ public final class ApiDocCommand {
|
|||||||
swaggerOperatMap.put("deprecated", true);
|
swaggerOperatMap.put("deprecated", true);
|
||||||
}
|
}
|
||||||
Map<String, Object> respSchemaMap = new LinkedHashMap<>();
|
Map<String, Object> respSchemaMap = new LinkedHashMap<>();
|
||||||
JsonFactory returnFactory = Rest.createJsonFactory(false, method.getAnnotationsByType(RestConvert.class), method.getAnnotationsByType(RestConvertCoder.class));
|
JsonFactory returnFactory = Rest.createJsonFactory(0, method.getAnnotationsByType(RestConvert.class), method.getAnnotationsByType(RestConvertCoder.class));
|
||||||
simpleSchemaType(returnFactory, node.getLogger(), swaggerComponentsMap, action.result(), resultType, respSchemaMap, true);
|
simpleSchemaType(returnFactory, node.getLogger(), swaggerComponentsMap, action.result(), resultType, respSchemaMap, true);
|
||||||
|
|
||||||
Map<String, Object> respMap = new LinkedHashMap<>();
|
Map<String, Object> respMap = new LinkedHashMap<>();
|
||||||
@@ -762,6 +762,6 @@ public final class ApiDocCommand {
|
|||||||
return example;
|
return example;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final JsonFactory exampleFactory = JsonFactory.create().tiny(false).nullable(false);
|
private static final JsonFactory exampleFactory = JsonFactory.create().features(0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ import java.lang.reflect.Type;
|
|||||||
*/
|
*/
|
||||||
public abstract class BinaryConvert<R extends Reader, W extends Writer> extends Convert<R, W> {
|
public abstract class BinaryConvert<R extends Reader, W extends Writer> extends Convert<R, W> {
|
||||||
|
|
||||||
protected BinaryConvert(ConvertFactory<R, W> factory) {
|
protected BinaryConvert(ConvertFactory<R, W> factory, int features) {
|
||||||
super(factory);
|
super(factory, features);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -24,8 +24,11 @@ public abstract class Convert<R extends Reader, W extends Writer> {
|
|||||||
|
|
||||||
protected final ConvertFactory<R, W> factory;
|
protected final ConvertFactory<R, W> factory;
|
||||||
|
|
||||||
protected Convert(ConvertFactory<R, W> factory) {
|
protected final int features;
|
||||||
|
|
||||||
|
protected Convert(ConvertFactory<R, W> factory, int features) {
|
||||||
this.factory = factory;
|
this.factory = factory;
|
||||||
|
this.features = features;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConvertFactory<R, W> getFactory() {
|
public ConvertFactory<R, W> getFactory() {
|
||||||
|
|||||||
@@ -36,6 +36,12 @@ import org.redkale.util.*;
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
||||||
|
|
||||||
|
//值为true时 String类型值为"",Boolean类型值为false时不会输出,默认为false
|
||||||
|
public static final int FEATURE_TINY = 1 << 1;
|
||||||
|
|
||||||
|
//值为true时 字段值为null时会输出,默认为false
|
||||||
|
public static final int FEATURE_NULLABLE = 1 << 2;
|
||||||
|
|
||||||
private static final AtomicBoolean loaderInited = new AtomicBoolean();
|
private static final AtomicBoolean loaderInited = new AtomicBoolean();
|
||||||
|
|
||||||
private static Convert defProtobufConvert;
|
private static Convert defProtobufConvert;
|
||||||
@@ -44,9 +50,8 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
|||||||
|
|
||||||
protected Convert<R, W> convert;
|
protected Convert<R, W> convert;
|
||||||
|
|
||||||
protected boolean tiny; //值为true时 String类型值为"",Boolean类型值为false时不会输出,默认为false
|
//配置属性集合, 1<<1至1<<10为系统内置
|
||||||
|
protected int features;
|
||||||
protected boolean nullable; ///值为true时 字段值为null时会输出,默认为false
|
|
||||||
|
|
||||||
private final Encodeable<W, ?> anyEncoder = new AnyEncoder(this);
|
private final Encodeable<W, ?> anyEncoder = new AnyEncoder(this);
|
||||||
|
|
||||||
@@ -74,9 +79,8 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
|||||||
|
|
||||||
private boolean skipAllIgnore = false;
|
private boolean skipAllIgnore = false;
|
||||||
|
|
||||||
protected ConvertFactory(ConvertFactory<R, W> parent, boolean tiny, boolean nullable) {
|
protected ConvertFactory(ConvertFactory<R, W> parent, int features) {
|
||||||
this.tiny = tiny;
|
this.features = features;
|
||||||
this.nullable = nullable;
|
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
if (parent == null) {
|
if (parent == null) {
|
||||||
//---------------------------------------------------------
|
//---------------------------------------------------------
|
||||||
@@ -209,6 +213,17 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final int features() {
|
||||||
|
return this.features;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConvertFactory features(int features) {
|
||||||
|
if (features > -1) {
|
||||||
|
this.features = features;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public ConvertFactory parent() {
|
public ConvertFactory parent() {
|
||||||
return this.parent;
|
return this.parent;
|
||||||
}
|
}
|
||||||
@@ -242,8 +257,8 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
|||||||
return type == ConvertType.PROTOBUF ? defProtobufConvert : null;
|
return type == ConvertType.PROTOBUF ? defProtobufConvert : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static boolean getSystemPropertyBoolean(String key, String parentkey, boolean defvalue) {
|
protected static int getSystemPropertyInt(String key, String parentkey, boolean defvalue, int feature) {
|
||||||
return Boolean.parseBoolean(System.getProperty(key, System.getProperty(parentkey, String.valueOf(defvalue))));
|
return Boolean.parseBoolean(System.getProperty(key, System.getProperty(parentkey, String.valueOf(defvalue)))) ? feature : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract ConvertType getConvertType();
|
public abstract ConvertType getConvertType();
|
||||||
@@ -254,7 +269,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
|||||||
|
|
||||||
public abstract ConvertFactory createChild();
|
public abstract ConvertFactory createChild();
|
||||||
|
|
||||||
public abstract ConvertFactory createChild(boolean tiny, boolean nullable);
|
public abstract ConvertFactory createChild(int features);
|
||||||
|
|
||||||
protected SimpledCoder createEnumSimpledCoder(Class enumClass) {
|
protected SimpledCoder createEnumSimpledCoder(Class enumClass) {
|
||||||
return new EnumSimpledCoder(this, enumClass);
|
return new EnumSimpledCoder(this, enumClass);
|
||||||
@@ -333,13 +348,29 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
|
|||||||
return convert;
|
return convert;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean tinyFeature(int features) {
|
||||||
|
return (features & FEATURE_TINY) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean nullableFeature(int features) {
|
||||||
|
return (features & FEATURE_NULLABLE) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
public ConvertFactory tiny(boolean tiny) {
|
public ConvertFactory tiny(boolean tiny) {
|
||||||
this.tiny = tiny;
|
if (tiny) {
|
||||||
|
this.features |= FEATURE_TINY;
|
||||||
|
} else {
|
||||||
|
this.features = this.features & ~FEATURE_TINY;
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConvertFactory nullable(boolean nullable) {
|
public ConvertFactory nullable(boolean nullable) {
|
||||||
this.nullable = nullable;
|
if (nullable) {
|
||||||
|
this.features |= FEATURE_NULLABLE;
|
||||||
|
} else {
|
||||||
|
this.features = this.features & ~FEATURE_NULLABLE;
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ import java.lang.reflect.Type;
|
|||||||
*/
|
*/
|
||||||
public abstract class TextConvert<R extends Reader, W extends Writer> extends Convert<R, W> {
|
public abstract class TextConvert<R extends Reader, W extends Writer> extends Convert<R, W> {
|
||||||
|
|
||||||
protected TextConvert(ConvertFactory<R, W> factory) {
|
protected TextConvert(ConvertFactory<R, W> factory, int features) {
|
||||||
super(factory);
|
super(factory, features);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ public abstract class Writer {
|
|||||||
//对某个对象进行动态扩展字段值处理
|
//对某个对象进行动态扩展字段值处理
|
||||||
protected Function<Object, ConvertField[]> objExtFunc;
|
protected Function<Object, ConvertField[]> objExtFunc;
|
||||||
|
|
||||||
|
//配置项
|
||||||
|
protected int features;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置specificObjectType
|
* 设置specificObjectType
|
||||||
*
|
*
|
||||||
@@ -69,18 +72,27 @@ public abstract class Writer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 当tiny=true时, 字符串为空、boolean为false的字段值都会被跳过, 不会输出。
|
* 获取配置属性
|
||||||
*
|
*
|
||||||
* @return 是否简化
|
|
||||||
*/
|
*/
|
||||||
public abstract boolean tiny();
|
public final int features() {
|
||||||
|
return features;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
public Writer features(int features) {
|
||||||
* 当nullable=true时, 字段值为null时会输出该字段
|
if (features > -1) {
|
||||||
*
|
this.features = features;
|
||||||
* @return 是否简化
|
}
|
||||||
*/
|
return this;
|
||||||
public abstract boolean nullable();
|
}
|
||||||
|
|
||||||
|
protected final boolean tiny() {
|
||||||
|
return ConvertFactory.tinyFeature(features);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final boolean nullable() {
|
||||||
|
return ConvertFactory.nullableFeature(features);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 输出null值
|
* 输出null值
|
||||||
|
|||||||
@@ -26,13 +26,12 @@ public class BsonByteBufferWriter extends BsonWriter {
|
|||||||
private int index;
|
private int index;
|
||||||
|
|
||||||
public BsonByteBufferWriter(Supplier<ByteBuffer> supplier) {
|
public BsonByteBufferWriter(Supplier<ByteBuffer> supplier) {
|
||||||
this(false, false, supplier);
|
this(0, supplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected BsonByteBufferWriter(boolean tiny, boolean nullable, Supplier<ByteBuffer> supplier) {
|
protected BsonByteBufferWriter(int features, Supplier<ByteBuffer> supplier) {
|
||||||
super((byte[]) null);
|
super((byte[]) null);
|
||||||
this.tiny = tiny;
|
this.features = features;
|
||||||
this.nullable = nullable;
|
|
||||||
this.supplier = supplier;
|
this.supplier = supplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,14 +71,8 @@ public class BsonByteBufferWriter extends BsonWriter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BsonByteBufferWriter tiny(boolean tiny) {
|
public BsonByteBufferWriter features(int features) {
|
||||||
this.tiny = tiny;
|
this.features = features;
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BsonByteBufferWriter nullable(boolean nullable) {
|
|
||||||
this.nullable = nullable;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,14 +46,8 @@ public class BsonConvert extends BinaryConvert<BsonReader, BsonWriter> {
|
|||||||
|
|
||||||
private final ThreadLocal<BsonReader> readerPool = ThreadLocal.withInitial(BsonReader::new);
|
private final ThreadLocal<BsonReader> readerPool = ThreadLocal.withInitial(BsonReader::new);
|
||||||
|
|
||||||
private final boolean tiny;
|
protected BsonConvert(ConvertFactory<BsonReader, BsonWriter> factory, int features) {
|
||||||
|
super(factory, features);
|
||||||
private final boolean nullable;
|
|
||||||
|
|
||||||
protected BsonConvert(ConvertFactory<BsonReader, BsonWriter> factory, boolean tiny, boolean nullable) {
|
|
||||||
super(factory);
|
|
||||||
this.tiny = tiny;
|
|
||||||
this.nullable = nullable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -82,7 +76,7 @@ public class BsonConvert extends BinaryConvert<BsonReader, BsonWriter> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BsonConvert newConvert(final BiFunction<Attribute, Object, Object> fieldFunc, BiFunction<Object, Object, Object> mapFieldFunc, Function<Object, ConvertField[]> objExtFunc) {
|
public BsonConvert newConvert(final BiFunction<Attribute, Object, Object> fieldFunc, BiFunction<Object, Object, Object> mapFieldFunc, Function<Object, ConvertField[]> objExtFunc) {
|
||||||
return new BsonConvert(getFactory(), tiny, nullable) {
|
return new BsonConvert(getFactory(), features) {
|
||||||
@Override
|
@Override
|
||||||
protected <S extends BsonWriter> S configWrite(S writer) {
|
protected <S extends BsonWriter> S configWrite(S writer) {
|
||||||
return fieldFunc(writer, fieldFunc, mapFieldFunc, objExtFunc);
|
return fieldFunc(writer, fieldFunc, mapFieldFunc, objExtFunc);
|
||||||
@@ -120,11 +114,11 @@ public class BsonConvert extends BinaryConvert<BsonReader, BsonWriter> {
|
|||||||
|
|
||||||
//------------------------------ writer -----------------------------------------------------------
|
//------------------------------ writer -----------------------------------------------------------
|
||||||
public BsonByteBufferWriter pollWriter(final Supplier<ByteBuffer> supplier) {
|
public BsonByteBufferWriter pollWriter(final Supplier<ByteBuffer> supplier) {
|
||||||
return configWrite(new BsonByteBufferWriter(tiny, nullable, supplier));
|
return configWrite(new BsonByteBufferWriter(features, supplier));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected BsonWriter pollWriter(final OutputStream out) {
|
protected BsonWriter pollWriter(final OutputStream out) {
|
||||||
return configWrite(new BsonStreamWriter(tiny, nullable, out));
|
return configWrite(new BsonStreamWriter(features, out));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -135,7 +129,7 @@ public class BsonConvert extends BinaryConvert<BsonReader, BsonWriter> {
|
|||||||
} else {
|
} else {
|
||||||
writerPool.set(null);
|
writerPool.set(null);
|
||||||
}
|
}
|
||||||
return configWrite(writer.tiny(tiny).nullable(nullable));
|
return configWrite(writer.features(features));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -240,7 +234,7 @@ public class BsonConvert extends BinaryConvert<BsonReader, BsonWriter> {
|
|||||||
@Override
|
@Override
|
||||||
public void convertToBytes(final ByteArray array, final Type type, final Object value) {
|
public void convertToBytes(final ByteArray array, final Type type, final Object value) {
|
||||||
Objects.requireNonNull(array);
|
Objects.requireNonNull(array);
|
||||||
final BsonWriter writer = configWrite(new BsonWriter(array).tiny(tiny).nullable(nullable));
|
final BsonWriter writer = configWrite(new BsonWriter(array).features(features));
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
writer.writeNull();
|
writer.writeNull();
|
||||||
} else {
|
} else {
|
||||||
@@ -286,7 +280,7 @@ public class BsonConvert extends BinaryConvert<BsonReader, BsonWriter> {
|
|||||||
if (value == null) {
|
if (value == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final BsonWriter writer = writerPool.get().tiny(tiny).nullable(nullable);
|
final BsonWriter writer = writerPool.get().features(features);
|
||||||
factory.loadEncoder(type == null ? value.getClass() : type).convertTo(writer, value);
|
factory.loadEncoder(type == null ? value.getClass() : type).convertTo(writer, value);
|
||||||
return writer;
|
return writer;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,8 +25,9 @@ import org.redkale.util.TypeToken;
|
|||||||
public final class BsonFactory extends ConvertFactory<BsonReader, BsonWriter> {
|
public final class BsonFactory extends ConvertFactory<BsonReader, BsonWriter> {
|
||||||
|
|
||||||
private static final BsonFactory instance = new BsonFactory(null,
|
private static final BsonFactory instance = new BsonFactory(null,
|
||||||
getSystemPropertyBoolean("redkale.convert.bson.tiny", "redkale.convert.tiny", true),
|
getSystemPropertyInt("redkale.convert.bson.tiny", "redkale.convert.tiny", true, FEATURE_TINY)
|
||||||
getSystemPropertyBoolean("redkale.convert.bson.nullable", "redkale.convert.nullable", false));
|
| getSystemPropertyInt("redkale.convert.bson.nullable", "redkale.convert.nullable", false, FEATURE_NULLABLE)
|
||||||
|
);
|
||||||
|
|
||||||
static final Decodeable objectDecoder = instance.loadDecoder(Object.class);
|
static final Decodeable objectDecoder = instance.loadDecoder(Object.class);
|
||||||
|
|
||||||
@@ -50,28 +51,28 @@ public final class BsonFactory extends ConvertFactory<BsonReader, BsonWriter> {
|
|||||||
//instance.register(AnyValue.class, instance.loadEncoder(AnyValue.DefaultAnyValue.class));
|
//instance.register(AnyValue.class, instance.loadEncoder(AnyValue.DefaultAnyValue.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
private BsonFactory(BsonFactory parent, boolean tiny, boolean nullable) {
|
private BsonFactory(BsonFactory parent, int features) {
|
||||||
super(parent, tiny, nullable);
|
super(parent, features);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BsonFactory tiny(boolean tiny) {
|
public BsonFactory tiny(boolean tiny) {
|
||||||
this.tiny = tiny;
|
super.tiny(tiny);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean tiny() {
|
protected boolean tiny() {
|
||||||
return this.tiny;
|
return (this.features & FEATURE_TINY) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BsonFactory nullable(boolean nullable) {
|
public BsonFactory nullable(boolean nullable) {
|
||||||
this.nullable = nullable;
|
super.nullable(nullable);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean nullable() {
|
protected boolean nullable() {
|
||||||
return this.nullable;
|
return (this.features & FEATURE_NULLABLE) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -85,26 +86,25 @@ public final class BsonFactory extends ConvertFactory<BsonReader, BsonWriter> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static BsonFactory create() {
|
public static BsonFactory create() {
|
||||||
return new BsonFactory(null, getSystemPropertyBoolean("redkale.convert.bson.tiny", "redkale.convert.tiny", true),
|
return new BsonFactory(null, instance.features);
|
||||||
getSystemPropertyBoolean("redkale.convert.bson.nullable", "redkale.convert.nullable", false));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final BsonConvert getConvert() {
|
public final BsonConvert getConvert() {
|
||||||
if (convert == null) {
|
if (convert == null) {
|
||||||
convert = new BsonConvert(this, tiny, nullable);
|
convert = new BsonConvert(this, features);
|
||||||
}
|
}
|
||||||
return (BsonConvert) convert;
|
return (BsonConvert) convert;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BsonFactory createChild() {
|
public BsonFactory createChild() {
|
||||||
return new BsonFactory(this, this.tiny, this.nullable);
|
return new BsonFactory(this, features);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BsonFactory createChild(boolean tiny, boolean nullable) {
|
public BsonFactory createChild(int features) {
|
||||||
return new BsonFactory(this, tiny, nullable);
|
return new BsonFactory(this, features);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ class BsonStreamWriter extends BsonByteBufferWriter {
|
|||||||
|
|
||||||
private OutputStream out;
|
private OutputStream out;
|
||||||
|
|
||||||
protected BsonStreamWriter(boolean tiny, boolean nullable, OutputStream out) {
|
protected BsonStreamWriter(int features, OutputStream out) {
|
||||||
super(tiny, nullable, null);
|
super(features, null);
|
||||||
this.out = out;
|
this.out = out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,10 +27,6 @@ public class BsonWriter extends Writer implements ByteTuple {
|
|||||||
|
|
||||||
protected int count;
|
protected int count;
|
||||||
|
|
||||||
protected boolean tiny = BsonFactory.root().tiny();
|
|
||||||
|
|
||||||
protected boolean nullable = BsonFactory.root().nullable();
|
|
||||||
|
|
||||||
public static ObjectPool<BsonWriter> createPool(int max) {
|
public static ObjectPool<BsonWriter> createPool(int max) {
|
||||||
return ObjectPool.createSafePool(max, (Object... params) -> new BsonWriter(), null, (t) -> t.recycle());
|
return ObjectPool.createSafePool(max, (Object... params) -> new BsonWriter(), null, (t) -> t.recycle());
|
||||||
}
|
}
|
||||||
@@ -86,6 +82,7 @@ public class BsonWriter extends Writer implements ByteTuple {
|
|||||||
|
|
||||||
public BsonWriter() {
|
public BsonWriter() {
|
||||||
this(defaultSize);
|
this(defaultSize);
|
||||||
|
this.features = BsonFactory.root().features();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BsonWriter(int size) {
|
public BsonWriter(int size) {
|
||||||
@@ -97,23 +94,8 @@ public class BsonWriter extends Writer implements ByteTuple {
|
|||||||
this.count = array.length();
|
this.count = array.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public BsonWriter features(int features) {
|
||||||
public final boolean tiny() {
|
super.features(features);
|
||||||
return tiny;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BsonWriter tiny(boolean tiny) {
|
|
||||||
this.tiny = tiny;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final boolean nullable() {
|
|
||||||
return nullable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BsonWriter nullable(boolean nullable) {
|
|
||||||
this.nullable = nullable;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,23 +34,16 @@ public class JsonByteBufferWriter extends JsonWriter {
|
|||||||
|
|
||||||
private int index;
|
private int index;
|
||||||
|
|
||||||
public JsonByteBufferWriter(boolean tiny, boolean nullable, Supplier<ByteBuffer> supplier) {
|
public JsonByteBufferWriter(int features, Supplier<ByteBuffer> supplier) {
|
||||||
this(tiny, nullable, null, supplier);
|
this(features, null, supplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JsonByteBufferWriter(boolean tiny, boolean nullable, Charset charset, Supplier<ByteBuffer> supplier) {
|
public JsonByteBufferWriter(int features, Charset charset, Supplier<ByteBuffer> supplier) {
|
||||||
this.tiny = tiny;
|
this.features = features;
|
||||||
this.nullable = nullable;
|
|
||||||
this.charset = charset;
|
this.charset = charset;
|
||||||
this.supplier = supplier;
|
this.supplier = supplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public JsonByteBufferWriter tiny(boolean tiny) {
|
|
||||||
this.tiny = tiny;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean recycle() {
|
protected boolean recycle() {
|
||||||
super.recycle();
|
super.recycle();
|
||||||
@@ -575,7 +568,7 @@ public class JsonByteBufferWriter extends JsonWriter {
|
|||||||
writeTo('}');
|
writeTo('}');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (value == null || (tiny && value.isEmpty())) {
|
if (value == null || (tiny() && value.isEmpty())) {
|
||||||
expand(1);
|
expand(1);
|
||||||
this.buffers[index].put((byte) '}');
|
this.buffers[index].put((byte) '}');
|
||||||
} else {
|
} else {
|
||||||
@@ -634,7 +627,7 @@ public class JsonByteBufferWriter extends JsonWriter {
|
|||||||
writeTo('}');
|
writeTo('}');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (value == null || (tiny && value.isEmpty())) {
|
if (value == null || (tiny() && value.isEmpty())) {
|
||||||
int expandsize = expand(2);
|
int expandsize = expand(2);
|
||||||
if (expandsize == 0) { // 只需要一个buffer
|
if (expandsize == 0) { // 只需要一个buffer
|
||||||
ByteBuffer bb = this.buffers[index];
|
ByteBuffer bb = this.buffers[index];
|
||||||
|
|||||||
@@ -55,9 +55,8 @@ public class JsonBytesWriter extends JsonWriter implements ByteTuple {
|
|||||||
this.count = array.length();
|
this.count = array.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
public JsonBytesWriter(boolean tiny, boolean nullable, ByteArray array) {
|
public JsonBytesWriter(int features, ByteArray array) {
|
||||||
this.tiny = tiny;
|
this.features = features;
|
||||||
this.nullable = nullable;
|
|
||||||
this.content = array.content();
|
this.content = array.content();
|
||||||
this.count = array.length();
|
this.count = array.length();
|
||||||
}
|
}
|
||||||
@@ -282,7 +281,7 @@ public class JsonBytesWriter extends JsonWriter implements ByteTuple {
|
|||||||
writeTo('}');
|
writeTo('}');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (value == null || (tiny && value.isEmpty())) {
|
if (value == null || (tiny() && value.isEmpty())) {
|
||||||
expand(1);
|
expand(1);
|
||||||
content[count++] = '}';
|
content[count++] = '}';
|
||||||
} else {
|
} else {
|
||||||
@@ -312,7 +311,7 @@ public class JsonBytesWriter extends JsonWriter implements ByteTuple {
|
|||||||
writeTo('}');
|
writeTo('}');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (value == null || (tiny && value.isEmpty())) {
|
if (value == null || (tiny() && value.isEmpty())) {
|
||||||
expand(2);
|
expand(2);
|
||||||
content[count++] = '{';
|
content[count++] = '{';
|
||||||
content[count++] = '}';
|
content[count++] = '}';
|
||||||
|
|||||||
@@ -40,18 +40,13 @@ public class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
|
|||||||
|
|
||||||
private final ThreadLocal<JsonReader> readerPool = ThreadLocal.withInitial(JsonReader::new);
|
private final ThreadLocal<JsonReader> readerPool = ThreadLocal.withInitial(JsonReader::new);
|
||||||
|
|
||||||
private final boolean tiny;
|
|
||||||
|
|
||||||
private final boolean nullable;
|
|
||||||
|
|
||||||
private Encodeable lastConvertEncodeable;
|
private Encodeable lastConvertEncodeable;
|
||||||
|
|
||||||
private Decodeable lastConvertDecodeable;
|
private Decodeable lastConvertDecodeable;
|
||||||
|
|
||||||
protected JsonConvert(JsonFactory factory, boolean tiny, boolean nullable) {
|
protected JsonConvert(JsonFactory factory, int features) {
|
||||||
super(factory);
|
super(factory, features);
|
||||||
this.tiny = tiny;
|
|
||||||
this.nullable = nullable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -80,7 +75,7 @@ public class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JsonConvert newConvert(final BiFunction<Attribute, Object, Object> objFieldFunc, BiFunction<Object, Object, Object> mapFieldFunc, Function<Object, ConvertField[]> objExtFunc) {
|
public JsonConvert newConvert(final BiFunction<Attribute, Object, Object> objFieldFunc, BiFunction<Object, Object, Object> mapFieldFunc, Function<Object, ConvertField[]> objExtFunc) {
|
||||||
return new JsonConvert(getFactory(), tiny, nullable) {
|
return new JsonConvert(getFactory(), features) {
|
||||||
@Override
|
@Override
|
||||||
protected <S extends JsonWriter> S configWrite(S writer) {
|
protected <S extends JsonWriter> S configWrite(S writer) {
|
||||||
return fieldFunc(writer, objFieldFunc, mapFieldFunc, objExtFunc);
|
return fieldFunc(writer, objFieldFunc, mapFieldFunc, objExtFunc);
|
||||||
@@ -115,7 +110,7 @@ public class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
|
|||||||
} else {
|
} else {
|
||||||
bytesWriterPool.set(null);
|
bytesWriterPool.set(null);
|
||||||
}
|
}
|
||||||
return configWrite((JsonBytesWriter) writer.tiny(tiny).nullable(nullable));
|
return configWrite((JsonBytesWriter) writer.features(features));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -135,7 +130,7 @@ public class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
|
|||||||
} else {
|
} else {
|
||||||
bytesWriterPool.set(null);
|
bytesWriterPool.set(null);
|
||||||
}
|
}
|
||||||
return configWrite((JsonBytesWriter) writer.tiny(tiny).nullable(nullable));
|
return configWrite((JsonBytesWriter) writer.features(features));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void offerJsonBytesWriter(final JsonBytesWriter writer) {
|
private void offerJsonBytesWriter(final JsonBytesWriter writer) {
|
||||||
@@ -395,7 +390,7 @@ public class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
|
|||||||
@Override
|
@Override
|
||||||
public void convertToBytes(final ByteArray array, final Type type, final Object value) {
|
public void convertToBytes(final ByteArray array, final Type type, final Object value) {
|
||||||
Objects.requireNonNull(array);
|
Objects.requireNonNull(array);
|
||||||
JsonBytesWriter writer = configWrite(new JsonBytesWriter(tiny, nullable, array));
|
JsonBytesWriter writer = configWrite(new JsonBytesWriter(features, array));
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
writer.writeNull();
|
writer.writeNull();
|
||||||
} else {
|
} else {
|
||||||
@@ -415,10 +410,10 @@ public class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
|
|||||||
|
|
||||||
public void convertTo(final OutputStream out, final Type type, final Object value) {
|
public void convertTo(final OutputStream out, final Type type, final Object value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
configWrite(new JsonStreamWriter(tiny, nullable, out)).writeNull();
|
configWrite(new JsonStreamWriter(features, out)).writeNull();
|
||||||
} else {
|
} else {
|
||||||
final Type t = type == null ? value.getClass() : type;
|
final Type t = type == null ? value.getClass() : type;
|
||||||
JsonStreamWriter writer = configWrite(new JsonStreamWriter(tiny, nullable, out));
|
JsonStreamWriter writer = configWrite(new JsonStreamWriter(features, out));
|
||||||
Encodeable encoder = this.lastConvertEncodeable;
|
Encodeable encoder = this.lastConvertEncodeable;
|
||||||
if (encoder == null || encoder.getType() != t) {
|
if (encoder == null || encoder.getType() != t) {
|
||||||
encoder = factory.loadEncoder(t);
|
encoder = factory.loadEncoder(t);
|
||||||
@@ -434,7 +429,7 @@ public class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
|
|||||||
@Override
|
@Override
|
||||||
public ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Type type, final Object value) {
|
public ByteBuffer[] convertTo(final Supplier<ByteBuffer> supplier, final Type type, final Object value) {
|
||||||
Objects.requireNonNull(supplier);
|
Objects.requireNonNull(supplier);
|
||||||
JsonByteBufferWriter out = configWrite(new JsonByteBufferWriter(tiny, nullable, supplier));
|
JsonByteBufferWriter out = configWrite(new JsonByteBufferWriter(features, supplier));
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
out.writeNull();
|
out.writeNull();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -386,7 +386,7 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
|
|||||||
final Map<String, AccessibleObject> mixedNames = mixedNames0;
|
final Map<String, AccessibleObject> mixedNames = mixedNames0;
|
||||||
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
|
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
|
||||||
final String newDynName = "org/redkaledyn/json/_Dyn" + JsonDynEncoder.class.getSimpleName()
|
final String newDynName = "org/redkaledyn/json/_Dyn" + JsonDynEncoder.class.getSimpleName()
|
||||||
+ "__" + clazz.getName().replace('.', '_').replace('$', '_') + "_" + factory.tiny() + "_" + factory.nullable() + "_" + Utility.md5Hex(memberb.toString()); //tiny必须要加上, 同一个类会有多个字段定制Convert
|
+ "__" + clazz.getName().replace('.', '_').replace('$', '_') + "_" + factory.features() + "_" + Utility.md5Hex(memberb.toString()); //tiny必须要加上, 同一个类会有多个字段定制Convert
|
||||||
try {
|
try {
|
||||||
Class clz = RedkaleClassLoader.findDynClass(newDynName.replace('/', '.'));
|
Class clz = RedkaleClassLoader.findDynClass(newDynName.replace('/', '.'));
|
||||||
Class newClazz = clz == null ? loader.loadClass(newDynName.replace('/', '.')) : clz;
|
Class newClazz = clz == null ? loader.loadClass(newDynName.replace('/', '.')) : clz;
|
||||||
@@ -511,8 +511,10 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
|
|||||||
|
|
||||||
int maxLocals = 4;
|
int maxLocals = 4;
|
||||||
int elementIndex = -1;
|
int elementIndex = -1;
|
||||||
|
final boolean tiny = ConvertFactory.tinyFeature(factory.features());
|
||||||
|
final boolean nullable = ConvertFactory.nullableFeature(factory.features());
|
||||||
final Class firstType = readGetSetFieldType(members.get(0));
|
final Class firstType = readGetSetFieldType(members.get(0));
|
||||||
final boolean mustHadComma = firstType.isPrimitive() && (firstType != boolean.class || !factory.tiny() || factory.nullable()); //byte/short/char/int/float/long/double
|
final boolean mustHadComma = firstType.isPrimitive() && (firstType != boolean.class || !tiny || nullable); //byte/short/char/int/float/long/double
|
||||||
|
|
||||||
if (onlyOneLatin1FieldObjectFlag) {
|
if (onlyOneLatin1FieldObjectFlag) {
|
||||||
//out.writeObjectByOnlyOneLatin1FieldValue(messageFirstFieldBytes, value.getMessage());elementIndex++;
|
//out.writeObjectByOnlyOneLatin1FieldValue(messageFirstFieldBytes, value.getMessage());elementIndex++;
|
||||||
@@ -670,16 +672,16 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Label msgnotemptyif = null;
|
Label msgnotemptyif = null;
|
||||||
if (!fieldtype.isPrimitive() && !factory.nullable()) { //if (message != null) { start
|
if (!fieldtype.isPrimitive() && !nullable) { //if (message != null) { start
|
||||||
mv.visitVarInsn(loadid, maxLocals);
|
mv.visitVarInsn(loadid, maxLocals);
|
||||||
msgnotemptyif = new Label();
|
msgnotemptyif = new Label();
|
||||||
mv.visitJumpInsn(IFNULL, msgnotemptyif);
|
mv.visitJumpInsn(IFNULL, msgnotemptyif);
|
||||||
if (factory.tiny() && fieldtype == String.class) {
|
if (tiny && fieldtype == String.class) {
|
||||||
mv.visitVarInsn(loadid, maxLocals);
|
mv.visitVarInsn(loadid, maxLocals);
|
||||||
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "isEmpty", "()Z", false);
|
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "isEmpty", "()Z", false);
|
||||||
mv.visitJumpInsn(IFNE, msgnotemptyif);
|
mv.visitJumpInsn(IFNE, msgnotemptyif);
|
||||||
}
|
}
|
||||||
} else if (fieldtype == boolean.class && factory.tiny()) {
|
} else if (fieldtype == boolean.class && tiny) {
|
||||||
mv.visitVarInsn(loadid, maxLocals);
|
mv.visitVarInsn(loadid, maxLocals);
|
||||||
msgnotemptyif = new Label();
|
msgnotemptyif = new Label();
|
||||||
mv.visitJumpInsn(IFEQ, msgnotemptyif);
|
mv.visitJumpInsn(IFEQ, msgnotemptyif);
|
||||||
@@ -794,10 +796,10 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
|
|||||||
mv.visitVarInsn(loadid, maxLocals);
|
mv.visitVarInsn(loadid, maxLocals);
|
||||||
mv.visitMethodInsn(INVOKEINTERFACE, encodeableName, "convertTo", "(" + writerDesc + "Ljava/lang/Object;)V", true);
|
mv.visitMethodInsn(INVOKEINTERFACE, encodeableName, "convertTo", "(" + writerDesc + "Ljava/lang/Object;)V", true);
|
||||||
}
|
}
|
||||||
if (!fieldtype.isPrimitive() && !factory.nullable()) { //if (message != null) } end
|
if (!fieldtype.isPrimitive() && !nullable) { //if (message != null) } end
|
||||||
mv.visitLabel(msgnotemptyif);
|
mv.visitLabel(msgnotemptyif);
|
||||||
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
|
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
|
||||||
} else if (fieldtype == boolean.class && factory.tiny()) {
|
} else if (fieldtype == boolean.class && tiny) {
|
||||||
mv.visitLabel(msgnotemptyif);
|
mv.visitLabel(msgnotemptyif);
|
||||||
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
|
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,8 +25,9 @@ import org.redkale.util.Uint128;
|
|||||||
public final class JsonFactory extends ConvertFactory<JsonReader, JsonWriter> {
|
public final class JsonFactory extends ConvertFactory<JsonReader, JsonWriter> {
|
||||||
|
|
||||||
private static final JsonFactory instance = new JsonFactory(null,
|
private static final JsonFactory instance = new JsonFactory(null,
|
||||||
getSystemPropertyBoolean("redkale.convert.json.tiny", "redkale.convert.tiny", false),
|
getSystemPropertyInt("redkale.convert.json.tiny", "redkale.convert.tiny", false, FEATURE_TINY)
|
||||||
getSystemPropertyBoolean("redkale.convert.json.nullable", "redkale.convert.nullable", false));
|
| getSystemPropertyInt("redkale.convert.json.nullable", "redkale.convert.nullable", false, FEATURE_NULLABLE)
|
||||||
|
);
|
||||||
|
|
||||||
static {
|
static {
|
||||||
instance.register(Serializable.class, instance.loadEncoder(Object.class));
|
instance.register(Serializable.class, instance.loadEncoder(Object.class));
|
||||||
@@ -35,8 +36,8 @@ public final class JsonFactory extends ConvertFactory<JsonReader, JsonWriter> {
|
|||||||
//instance.register(AnyValue.class, instance.loadEncoder(AnyValue.DefaultAnyValue.class));
|
//instance.register(AnyValue.class, instance.loadEncoder(AnyValue.DefaultAnyValue.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
private JsonFactory(JsonFactory parent, boolean tiny, boolean nullable) {
|
private JsonFactory(JsonFactory parent, int features) {
|
||||||
super(parent, tiny, nullable);
|
super(parent, features);
|
||||||
if (parent == null) {
|
if (parent == null) {
|
||||||
this.register(InetAddress.class, InetAddressSimpledCoder.InetAddressJsonSimpledCoder.instance);
|
this.register(InetAddress.class, InetAddressSimpledCoder.InetAddressJsonSimpledCoder.instance);
|
||||||
this.register(InetSocketAddress.class, InetAddressSimpledCoder.InetSocketAddressJsonSimpledCoder.instance);
|
this.register(InetSocketAddress.class, InetAddressSimpledCoder.InetSocketAddressJsonSimpledCoder.instance);
|
||||||
@@ -55,15 +56,8 @@ public final class JsonFactory extends ConvertFactory<JsonReader, JsonWriter> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public JsonFactory features(int features) {
|
||||||
public JsonFactory tiny(boolean tiny) {
|
this.features = features;
|
||||||
this.tiny = tiny;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JsonFactory nullable(boolean nullable) {
|
|
||||||
this.nullable = nullable;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,8 +72,7 @@ public final class JsonFactory extends ConvertFactory<JsonReader, JsonWriter> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static JsonFactory create() {
|
public static JsonFactory create() {
|
||||||
return new JsonFactory(null, getSystemPropertyBoolean("redkale.convert.json.tiny", "redkale.convert.tiny", false),
|
return new JsonFactory(null, instance.features());
|
||||||
getSystemPropertyBoolean("redkale.convert.json.nullable", "redkale.convert.nullable", false));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -97,30 +90,22 @@ public final class JsonFactory extends ConvertFactory<JsonReader, JsonWriter> {
|
|||||||
return new JsonMultiImplDecoder(this, types);
|
return new JsonMultiImplDecoder(this, types);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean tiny() {
|
|
||||||
return this.tiny;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean nullable() {
|
|
||||||
return this.nullable;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final JsonConvert getConvert() {
|
public final JsonConvert getConvert() {
|
||||||
if (convert == null) {
|
if (convert == null) {
|
||||||
convert = new JsonConvert(this, tiny, nullable);
|
convert = new JsonConvert(this, features);
|
||||||
}
|
}
|
||||||
return (JsonConvert) convert;
|
return (JsonConvert) convert;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JsonFactory createChild() {
|
public JsonFactory createChild() {
|
||||||
return new JsonFactory(this, this.tiny, this.nullable);
|
return new JsonFactory(this, this.features);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JsonFactory createChild(boolean tiny, boolean nullable) {
|
public JsonFactory createChild(int features) {
|
||||||
return new JsonFactory(this, tiny, nullable);
|
return new JsonFactory(this, features);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -21,12 +21,12 @@ class JsonStreamWriter extends JsonByteBufferWriter {
|
|||||||
|
|
||||||
private OutputStream out;
|
private OutputStream out;
|
||||||
|
|
||||||
protected JsonStreamWriter(boolean tiny, boolean nullable, OutputStream out) {
|
protected JsonStreamWriter(int features, OutputStream out) {
|
||||||
this(tiny, nullable, null, out);
|
this(features, null, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected JsonStreamWriter(boolean tiny, boolean nullable, Charset charset, OutputStream out) {
|
protected JsonStreamWriter(int features, Charset charset, OutputStream out) {
|
||||||
super(tiny, nullable, charset, null);
|
super(features, charset, null);
|
||||||
this.out = out;
|
this.out = out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,17 +21,12 @@ public abstract class JsonWriter extends Writer {
|
|||||||
|
|
||||||
protected static final int defaultSize = Integer.getInteger("redkale.convert.json.writer.buffer.defsize", Integer.getInteger("redkale.convert.writer.buffer.defsize", 1024));
|
protected static final int defaultSize = Integer.getInteger("redkale.convert.json.writer.buffer.defsize", Integer.getInteger("redkale.convert.writer.buffer.defsize", 1024));
|
||||||
|
|
||||||
protected boolean tiny = JsonFactory.root().tiny();
|
protected JsonWriter() {
|
||||||
|
this.features = JsonFactory.root().features();
|
||||||
protected boolean nullable = JsonFactory.root().nullable();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean tiny() {
|
|
||||||
return tiny;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public JsonWriter tiny(boolean tiny) {
|
public JsonWriter features(int features) {
|
||||||
this.tiny = tiny;
|
super.features(features);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,16 +35,6 @@ public abstract class JsonWriter extends Writer {
|
|||||||
return this.objExtFunc == null && this.objFieldFunc == null;
|
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 的字符
|
public abstract void writeTo(final char ch); //只能是 0 - 127 的字符
|
||||||
|
|
||||||
|
|||||||
@@ -172,14 +172,17 @@ public final class Rest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static JsonFactory createJsonFactory(RestConvert[] converts, RestConvertCoder[] coders) {
|
public static JsonFactory createJsonFactory(RestConvert[] converts, RestConvertCoder[] coders) {
|
||||||
return createJsonFactory(true, converts, coders);
|
return createJsonFactory(-1, converts, coders);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static JsonFactory createJsonFactory(boolean tiny, RestConvert[] converts, RestConvertCoder[] coders) {
|
public static JsonFactory createJsonFactory(int features, RestConvert[] converts, RestConvertCoder[] coders) {
|
||||||
if ((converts == null || converts.length < 1) && (coders == null || coders.length < 1)) {
|
if ((converts == null || converts.length < 1) && (coders == null || coders.length < 1)) {
|
||||||
return JsonFactory.root();
|
return JsonFactory.root();
|
||||||
}
|
}
|
||||||
final JsonFactory childFactory = JsonFactory.create().tiny(tiny);
|
final JsonFactory childFactory = JsonFactory.create();
|
||||||
|
if (features > -1) {
|
||||||
|
childFactory.features(features);
|
||||||
|
}
|
||||||
List<Class> types = new ArrayList<>();
|
List<Class> types = new ArrayList<>();
|
||||||
Set<Class> reloadTypes = new HashSet<>();
|
Set<Class> reloadTypes = new HashSet<>();
|
||||||
if (coders != null) {
|
if (coders != null) {
|
||||||
@@ -208,8 +211,8 @@ public final class Rest {
|
|||||||
childFactory.reloadCoder(rc.type());
|
childFactory.reloadCoder(rc.type());
|
||||||
}
|
}
|
||||||
types.add(rc.type());
|
types.add(rc.type());
|
||||||
if (tiny) {
|
if (rc.features() > -1) {
|
||||||
childFactory.tiny(rc.tiny());
|
childFactory.features(rc.features());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2287,7 +2290,7 @@ public final class Rest {
|
|||||||
//设置 RestConvert
|
//设置 RestConvert
|
||||||
for (RestConvert rc : rcs) {
|
for (RestConvert rc : rcs) {
|
||||||
AnnotationVisitor av2 = av1.visitAnnotation(null, restConvertDesc);
|
AnnotationVisitor av2 = av1.visitAnnotation(null, restConvertDesc);
|
||||||
av2.visit("tiny", rc.tiny());
|
av2.visit("features", rc.features());
|
||||||
av2.visit("skipIgnore", rc.skipIgnore());
|
av2.visit("skipIgnore", rc.skipIgnore());
|
||||||
av2.visit("type", Type.getType(Type.getDescriptor(rc.type())));
|
av2.visit("type", Type.getType(Type.getDescriptor(rc.type())));
|
||||||
AnnotationVisitor av3 = av2.visitArray("onlyColumns");
|
AnnotationVisitor av3 = av2.visitArray("onlyColumns");
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.redkale.net.http;
|
package org.redkale.net.http;
|
||||||
|
|
||||||
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
import static java.lang.annotation.ElementType.*;
|
import static java.lang.annotation.ElementType.*;
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 只能依附在Service实现类的public方法上, 当方法的返回值以JSON输出时对指定类型的转换设定。 <br>
|
* 只能依附在Service实现类的public方法上, 当方法的返回值以JSON输出时对指定类型的转换设定。 <br>
|
||||||
@@ -26,11 +26,11 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|||||||
public @interface RestConvert {
|
public @interface RestConvert {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否输出空字符串,0数值
|
* 配置项
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return int
|
||||||
*/
|
*/
|
||||||
boolean tiny() default true;
|
int features() default -1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否忽略ConvertColumn.ignore=true的设置, 优先级最高
|
* 是否忽略ConvertColumn.ignore=true的设置, 优先级最高
|
||||||
|
|||||||
18
src/main/java/org/redkale/source/CacheEventListener.java
Normal file
18
src/main/java/org/redkale/source/CacheEventListener.java
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.redkale.source;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CacheSource订阅频道的消费监听器
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
* @since 2.8.0
|
||||||
|
*/
|
||||||
|
public interface CacheEventListener<T> {
|
||||||
|
|
||||||
|
public void onMessage(String topic, T message);
|
||||||
|
}
|
||||||
@@ -161,6 +161,26 @@ public final class CacheMemorySource extends AbstractCacheSource {
|
|||||||
return CompletableFuture.completedFuture(true);
|
return CompletableFuture.completedFuture(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------ 订阅发布 SUB/PUB ------------------------
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<List<String>> pubsubChannelsAsync(@Nullable String pattern){
|
||||||
|
throw new UnsupportedOperationException("Not supported yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<Void> subscribeAsync(CacheEventListener<byte[]> consumer, String... topics) {
|
||||||
|
Objects.requireNonNull(consumer);
|
||||||
|
throw new UnsupportedOperationException("Not supported yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<Integer> publishAsync(String topic, byte[] message) {
|
||||||
|
Objects.requireNonNull(topic);
|
||||||
|
Objects.requireNonNull(message);
|
||||||
|
throw new UnsupportedOperationException("Not supported yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------ 字符串 String ------------------------
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Void> msetAsync(Serializable... keyVals) {
|
public CompletableFuture<Void> msetAsync(Serializable... keyVals) {
|
||||||
return runFuture(() -> {
|
return runFuture(() -> {
|
||||||
|
|||||||
@@ -10,8 +10,9 @@ import java.lang.reflect.Type;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
import org.redkale.annotation.Component;
|
import org.redkale.annotation.*;
|
||||||
import org.redkale.convert.Convert;
|
import org.redkale.convert.Convert;
|
||||||
|
import org.redkale.convert.json.JsonConvert;
|
||||||
import org.redkale.util.*;
|
import org.redkale.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,6 +37,79 @@ public interface CacheSource extends Resourcable {
|
|||||||
return isOpenAsync().join();
|
return isOpenAsync().join();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------ 订阅发布 SUB/PUB ------------------------
|
||||||
|
default List<String> pubsubChannels(@Nullable String pattern) {
|
||||||
|
return pubsubChannelsAsync(pattern).join();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompletableFuture<List<String>> pubsubChannelsAsync(@Nullable String pattern);
|
||||||
|
|
||||||
|
//------------------------ 订阅 SUB ------------------------
|
||||||
|
default <T> void subscribe(Type messageType, CacheEventListener<T> listener, String... topics) {
|
||||||
|
subscribe(JsonConvert.root(), messageType, listener, topics);
|
||||||
|
}
|
||||||
|
|
||||||
|
default <T> void subscribe(Convert convert, Type messageType, CacheEventListener<T> listener, String... topics) {
|
||||||
|
final Convert c = convert == null ? JsonConvert.root() : convert;
|
||||||
|
subscribe((t, bs) -> listener.onMessage(t, bs == null ? null : (T) c.convertFrom(messageType, bs)), topics);
|
||||||
|
}
|
||||||
|
|
||||||
|
default void subscribe(CacheEventListener<byte[]> listener, String... topics) {
|
||||||
|
subscribeAsync(listener, topics).join();
|
||||||
|
}
|
||||||
|
|
||||||
|
default <T> CompletableFuture<Void> subscribeAsync(Type messageType, CacheEventListener<T> listener, String... topics) {
|
||||||
|
return subscribeAsync(JsonConvert.root(), messageType, listener, topics);
|
||||||
|
}
|
||||||
|
|
||||||
|
default <T> CompletableFuture<Void> subscribeAsync(Convert convert, Type messageType, CacheEventListener<T> listener, String... topics) {
|
||||||
|
final Convert c = convert == null ? JsonConvert.root() : convert;
|
||||||
|
return subscribeAsync((t, bs) -> listener.onMessage(t, bs == null ? null : (T) c.convertFrom(messageType, bs)), topics);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompletableFuture<Void> subscribeAsync(CacheEventListener<byte[]> listener, String... topics);
|
||||||
|
|
||||||
|
//------------------------ 发布 PUB ------------------------
|
||||||
|
default <T> int publish(String topic, T message) {
|
||||||
|
return publish(topic, JsonConvert.root(), message.getClass(), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
default <T> int publish(String topic, Convert convert, T message) {
|
||||||
|
return publish(topic, convert, message.getClass(), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
default <T> int publish(String topic, Type messageType, T message) {
|
||||||
|
return publish(topic, JsonConvert.root(), messageType, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
default <T> int publish(String topic, Convert convert, Type messageType, T message) {
|
||||||
|
final Convert c = convert == null ? JsonConvert.root() : convert;
|
||||||
|
return publish(topic, c.convertToBytes(messageType, message));
|
||||||
|
}
|
||||||
|
|
||||||
|
default int publish(String topic, byte[] message) {
|
||||||
|
return publishAsync(topic, message).join();
|
||||||
|
}
|
||||||
|
|
||||||
|
default <T> CompletableFuture<Integer> publishAsync(String topic, T message) {
|
||||||
|
return publishAsync(topic, JsonConvert.root(), message.getClass(), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
default <T> CompletableFuture<Integer> publishAsync(String topic, Convert convert, T message) {
|
||||||
|
return publishAsync(topic, convert, message.getClass(), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
default <T> CompletableFuture<Integer> publishAsync(String topic, Type messageType, T message) {
|
||||||
|
return publishAsync(topic, JsonConvert.root(), messageType, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
default <T> CompletableFuture<Integer> publishAsync(String topic, Convert convert, Type messageType, T message) {
|
||||||
|
final Convert c = convert == null ? JsonConvert.root() : convert;
|
||||||
|
return publishAsync(topic, c.convertToBytes(messageType, message));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompletableFuture<Integer> publishAsync(String topic, byte[] message);
|
||||||
|
|
||||||
//------------------------ 字符串 String ------------------------
|
//------------------------ 字符串 String ------------------------
|
||||||
default long incr(String key) {
|
default long incr(String key) {
|
||||||
return incrAsync(key).join();
|
return incrAsync(key).join();
|
||||||
|
|||||||
643
src/main/java/org/redkale/util/CronExpression.java
Normal file
643
src/main/java/org/redkale/util/CronExpression.java
Normal file
@@ -0,0 +1,643 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.redkale.util;
|
||||||
|
|
||||||
|
import java.time.DateTimeException;
|
||||||
|
import java.time.temporal.*;
|
||||||
|
import java.util.*;
|
||||||
|
import org.redkale.annotation.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cron定时表达式解析器 <br> 代码复制于org.springframework.scheduling.support.CronExpression
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 详情见: https://redkale.org
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
* @since 2.8.0
|
||||||
|
*/
|
||||||
|
public class CronExpression {
|
||||||
|
|
||||||
|
static final int MAX_ATTEMPTS = 366;
|
||||||
|
|
||||||
|
private static final String[] MACROS = new String[]{
|
||||||
|
"@yearly", "0 0 0 1 1 *",
|
||||||
|
"@annually", "0 0 0 1 1 *",
|
||||||
|
"@monthly", "0 0 0 1 * *",
|
||||||
|
"@weekly", "0 0 0 * * 0",
|
||||||
|
"@daily", "0 0 0 * * *",
|
||||||
|
"@midnight", "0 0 0 * * *",
|
||||||
|
"@hourly", "0 0 * * * *"
|
||||||
|
};
|
||||||
|
|
||||||
|
private final CronField[] fields;
|
||||||
|
|
||||||
|
private final String expression;
|
||||||
|
|
||||||
|
private CronExpression(CronField seconds, CronField minutes, CronField hours,
|
||||||
|
CronField daysOfMonth, CronField months, CronField daysOfWeek, String expression) {
|
||||||
|
this.fields = new CronField[]{daysOfWeek, months, daysOfMonth, hours, minutes, seconds, CronField.zeroNanos()};
|
||||||
|
this.expression = expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CronExpression parse(String expression) {
|
||||||
|
if (Utility.isBlank(expression)) {
|
||||||
|
throw new RedkaleException("Expression string must not be empty");
|
||||||
|
}
|
||||||
|
expression = resolveMacros(expression);
|
||||||
|
String[] fields = expression.split("\\s+");
|
||||||
|
if (fields.length != 6) {
|
||||||
|
throw new RedkaleException(String.format("Cron expression must consist of 6 fields (found %d in \"%s\")", fields.length, expression));
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
CronField seconds = CronField.parseSeconds(fields[0]);
|
||||||
|
CronField minutes = CronField.parseMinutes(fields[1]);
|
||||||
|
CronField hours = CronField.parseHours(fields[2]);
|
||||||
|
CronField daysOfMonth = CronField.parseDaysOfMonth(fields[3]);
|
||||||
|
CronField months = CronField.parseMonth(fields[4]);
|
||||||
|
CronField daysOfWeek = CronField.parseDaysOfWeek(fields[5]);
|
||||||
|
return new CronExpression(seconds, minutes, hours, daysOfMonth, months, daysOfWeek, expression);
|
||||||
|
} catch (IllegalArgumentException ex) {
|
||||||
|
String msg = ex.getMessage() + " in cron expression \"" + expression + "\"";
|
||||||
|
throw new RedkaleException(msg, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String resolveMacros(String expression) {
|
||||||
|
expression = expression.trim();
|
||||||
|
for (int i = 0; i < MACROS.length; i = i + 2) {
|
||||||
|
if (MACROS[i].equalsIgnoreCase(expression)) {
|
||||||
|
return MACROS[i + 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public <T extends Temporal & Comparable<? super T>> T next(T temporal) {
|
||||||
|
return nextOrSame(ChronoUnit.NANOS.addTo(temporal, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private <T extends Temporal & Comparable<? super T>> T nextOrSame(T temporal) {
|
||||||
|
for (int i = 0; i < MAX_ATTEMPTS; i++) {
|
||||||
|
T result = nextOrSameInternal(temporal);
|
||||||
|
if (result == null || result.equals(temporal)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
temporal = result;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private <T extends Temporal & Comparable<? super T>> T nextOrSameInternal(T temporal) {
|
||||||
|
for (CronField field : this.fields) {
|
||||||
|
temporal = field.nextOrSame(temporal);
|
||||||
|
if (temporal == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return temporal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(@Nullable Object other) {
|
||||||
|
if (this == other) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(other instanceof CronExpression)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
CronExpression that = (CronExpression) other;
|
||||||
|
return Arrays.equals(this.fields, that.fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Arrays.hashCode(this.fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract static class CronField {
|
||||||
|
|
||||||
|
private static final String[] MONTHS = new String[]{"JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP",
|
||||||
|
"OCT", "NOV", "DEC"};
|
||||||
|
|
||||||
|
private static final String[] DAYS = new String[]{"MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"};
|
||||||
|
|
||||||
|
private final Type type;
|
||||||
|
|
||||||
|
protected CronField(Type type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CronField zeroNanos() {
|
||||||
|
return BitsCronField.zeroNanos();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CronField parseSeconds(String value) {
|
||||||
|
return BitsCronField.parseSeconds(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CronField parseMinutes(String value) {
|
||||||
|
return BitsCronField.parseMinutes(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CronField parseHours(String value) {
|
||||||
|
return BitsCronField.parseHours(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CronField parseDaysOfMonth(String value) {
|
||||||
|
return BitsCronField.parseDaysOfMonth(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CronField parseMonth(String value) {
|
||||||
|
value = replaceOrdinals(value, MONTHS);
|
||||||
|
return BitsCronField.parseMonth(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CronField parseDaysOfWeek(String value) {
|
||||||
|
value = replaceOrdinals(value, DAYS);
|
||||||
|
return BitsCronField.parseDaysOfWeek(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String replaceOrdinals(String value, String[] list) {
|
||||||
|
value = value.toUpperCase();
|
||||||
|
for (int i = 0; i < list.length; i++) {
|
||||||
|
String replacement = Integer.toString(i + 1);
|
||||||
|
value = replace(value, list[i], replacement);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String replace(String inString, String oldPattern, @Nullable String newPattern) {
|
||||||
|
if (Utility.isEmpty(inString) || Utility.isEmpty(oldPattern) || newPattern == null) {
|
||||||
|
return inString;
|
||||||
|
}
|
||||||
|
int index = inString.indexOf(oldPattern);
|
||||||
|
if (index == -1) {
|
||||||
|
// no occurrence -> can return input as-is
|
||||||
|
return inString;
|
||||||
|
}
|
||||||
|
|
||||||
|
int capacity = inString.length();
|
||||||
|
if (newPattern.length() > oldPattern.length()) {
|
||||||
|
capacity += 16;
|
||||||
|
}
|
||||||
|
StringBuilder sb = new StringBuilder(capacity);
|
||||||
|
|
||||||
|
int pos = 0; // our position in the old string
|
||||||
|
int patLen = oldPattern.length();
|
||||||
|
while (index >= 0) {
|
||||||
|
sb.append(inString, pos, index);
|
||||||
|
sb.append(newPattern);
|
||||||
|
pos = index + patLen;
|
||||||
|
index = inString.indexOf(oldPattern, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// append any characters to the right of a match
|
||||||
|
sb.append(inString, pos, inString.length());
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String[] delimitedListToStringArray(@Nullable String str, @Nullable String delimiter) {
|
||||||
|
return delimitedListToStringArray(str, delimiter, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String[] delimitedListToStringArray(String str, String delimiter, String charsToDelete) {
|
||||||
|
|
||||||
|
if (str == null) {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
if (delimiter == null) {
|
||||||
|
return new String[]{str};
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> result = new ArrayList<>();
|
||||||
|
if (delimiter.isEmpty()) {
|
||||||
|
for (int i = 0; i < str.length(); i++) {
|
||||||
|
result.add(deleteAny(str.substring(i, i + 1), charsToDelete));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int pos = 0;
|
||||||
|
int delPos;
|
||||||
|
while ((delPos = str.indexOf(delimiter, pos)) != -1) {
|
||||||
|
result.add(deleteAny(str.substring(pos, delPos), charsToDelete));
|
||||||
|
pos = delPos + delimiter.length();
|
||||||
|
}
|
||||||
|
if (str.length() > 0 && pos <= str.length()) {
|
||||||
|
// Add rest of String, but not in case of empty input.
|
||||||
|
result.add(deleteAny(str.substring(pos), charsToDelete));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toArray(new String[result.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String deleteAny(String inString, @Nullable String charsToDelete) {
|
||||||
|
if (Utility.isEmpty(inString) || Utility.isEmpty(charsToDelete)) {
|
||||||
|
return inString;
|
||||||
|
}
|
||||||
|
int lastCharIndex = 0;
|
||||||
|
char[] result = new char[inString.length()];
|
||||||
|
for (int i = 0; i < inString.length(); i++) {
|
||||||
|
char c = inString.charAt(i);
|
||||||
|
if (charsToDelete.indexOf(c) == -1) {
|
||||||
|
result[lastCharIndex++] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lastCharIndex == inString.length()) {
|
||||||
|
return inString;
|
||||||
|
}
|
||||||
|
return new String(result, 0, lastCharIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public abstract <T extends Temporal & Comparable<? super T>> T nextOrSame(T temporal);
|
||||||
|
|
||||||
|
protected Type type() {
|
||||||
|
return this.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected static <T extends Temporal & Comparable<? super T>> T cast(Temporal temporal) {
|
||||||
|
return (T) temporal;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected enum Type {
|
||||||
|
NANO(ChronoField.NANO_OF_SECOND, ChronoUnit.SECONDS),
|
||||||
|
SECOND(ChronoField.SECOND_OF_MINUTE, ChronoUnit.MINUTES, ChronoField.NANO_OF_SECOND),
|
||||||
|
MINUTE(ChronoField.MINUTE_OF_HOUR, ChronoUnit.HOURS, ChronoField.SECOND_OF_MINUTE, ChronoField.NANO_OF_SECOND),
|
||||||
|
HOUR(ChronoField.HOUR_OF_DAY, ChronoUnit.DAYS, ChronoField.MINUTE_OF_HOUR, ChronoField.SECOND_OF_MINUTE, ChronoField.NANO_OF_SECOND),
|
||||||
|
DAY_OF_MONTH(ChronoField.DAY_OF_MONTH, ChronoUnit.MONTHS, ChronoField.HOUR_OF_DAY, ChronoField.MINUTE_OF_HOUR, ChronoField.SECOND_OF_MINUTE, ChronoField.NANO_OF_SECOND),
|
||||||
|
MONTH(ChronoField.MONTH_OF_YEAR, ChronoUnit.YEARS, ChronoField.DAY_OF_MONTH, ChronoField.HOUR_OF_DAY, ChronoField.MINUTE_OF_HOUR, ChronoField.SECOND_OF_MINUTE, ChronoField.NANO_OF_SECOND),
|
||||||
|
DAY_OF_WEEK(ChronoField.DAY_OF_WEEK, ChronoUnit.WEEKS, ChronoField.HOUR_OF_DAY, ChronoField.MINUTE_OF_HOUR, ChronoField.SECOND_OF_MINUTE, ChronoField.NANO_OF_SECOND);
|
||||||
|
|
||||||
|
private final ChronoField field;
|
||||||
|
|
||||||
|
private final ChronoUnit higherOrder;
|
||||||
|
|
||||||
|
private final ChronoField[] lowerOrders;
|
||||||
|
|
||||||
|
Type(ChronoField field, ChronoUnit higherOrder, ChronoField... lowerOrders) {
|
||||||
|
this.field = field;
|
||||||
|
this.higherOrder = higherOrder;
|
||||||
|
this.lowerOrders = lowerOrders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int get(Temporal date) {
|
||||||
|
return date.get(this.field);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueRange range() {
|
||||||
|
return this.field.range();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int checkValidValue(int value) {
|
||||||
|
if (this == DAY_OF_WEEK && value == 0) {
|
||||||
|
return value;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
return this.field.checkValidIntValue(value);
|
||||||
|
} catch (DateTimeException ex) {
|
||||||
|
throw new IllegalArgumentException(ex.getMessage(), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends Temporal & Comparable<? super T>> T elapseUntil(T temporal, int goal) {
|
||||||
|
int current = get(temporal);
|
||||||
|
ValueRange range = temporal.range(this.field);
|
||||||
|
if (current < goal) {
|
||||||
|
if (range.isValidIntValue(goal)) {
|
||||||
|
return cast(temporal.with(this.field, goal));
|
||||||
|
} else {
|
||||||
|
// goal is invalid, eg. 29th Feb, so roll forward
|
||||||
|
long amount = range.getMaximum() - current + 1;
|
||||||
|
return this.field.getBaseUnit().addTo(temporal, amount);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
long amount = goal + range.getMaximum() - current + 1 - range.getMinimum();
|
||||||
|
return this.field.getBaseUnit().addTo(temporal, amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends Temporal & Comparable<? super T>> T rollForward(T temporal) {
|
||||||
|
T result = this.higherOrder.addTo(temporal, 1);
|
||||||
|
ValueRange range = result.range(this.field);
|
||||||
|
return this.field.adjustInto(result, range.getMinimum());
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends Temporal> T reset(T temporal) {
|
||||||
|
for (ChronoField lowerOrder : this.lowerOrders) {
|
||||||
|
if (temporal.isSupported(lowerOrder)) {
|
||||||
|
temporal = lowerOrder.adjustInto(temporal, temporal.range(lowerOrder).getMinimum());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return temporal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.field.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class BitsCronField extends CronField {
|
||||||
|
|
||||||
|
private static final long MASK = 0xFFFFFFFFFFFFFFFFL;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static BitsCronField zeroNanos = null;
|
||||||
|
|
||||||
|
// we store at most 60 bits, for seconds and minutes, so a 64-bit long suffices
|
||||||
|
private long bits;
|
||||||
|
|
||||||
|
private BitsCronField(Type type) {
|
||||||
|
super(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BitsCronField zeroNanos() {
|
||||||
|
if (zeroNanos == null) {
|
||||||
|
BitsCronField field = new BitsCronField(Type.NANO);
|
||||||
|
field.setBit(0);
|
||||||
|
zeroNanos = field;
|
||||||
|
}
|
||||||
|
return zeroNanos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BitsCronField parseSeconds(String value) {
|
||||||
|
return parseField(value, Type.SECOND);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BitsCronField parseMinutes(String value) {
|
||||||
|
return BitsCronField.parseField(value, Type.MINUTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BitsCronField parseHours(String value) {
|
||||||
|
return BitsCronField.parseField(value, Type.HOUR);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BitsCronField parseDaysOfMonth(String value) {
|
||||||
|
return parseDate(value, Type.DAY_OF_MONTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BitsCronField parseMonth(String value) {
|
||||||
|
return BitsCronField.parseField(value, Type.MONTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BitsCronField parseDaysOfWeek(String value) {
|
||||||
|
BitsCronField result = parseDate(value, Type.DAY_OF_WEEK);
|
||||||
|
if (result.getBit(0)) {
|
||||||
|
// cron supports 0 for Sunday; we use 7 like java.time
|
||||||
|
result.setBit(7);
|
||||||
|
result.clearBit(0);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BitsCronField parseDate(String value, BitsCronField.Type type) {
|
||||||
|
if (value.equals("?")) {
|
||||||
|
value = "*";
|
||||||
|
}
|
||||||
|
return BitsCronField.parseField(value, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BitsCronField parseField(String value, Type type) {
|
||||||
|
if (Utility.isBlank(value)) {
|
||||||
|
throw new RedkaleException("Value must not be empty");
|
||||||
|
}
|
||||||
|
if (type == null) {
|
||||||
|
throw new RedkaleException("Type must not be null");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
BitsCronField result = new BitsCronField(type);
|
||||||
|
String[] fields = CronField.delimitedListToStringArray(value, ",");
|
||||||
|
for (String field : fields) {
|
||||||
|
int slashPos = field.indexOf('/');
|
||||||
|
if (slashPos == -1) {
|
||||||
|
ValueRange range = parseRange(field, type);
|
||||||
|
result.setBits(range);
|
||||||
|
} else {
|
||||||
|
String rangeStr = field.substring(0, slashPos);
|
||||||
|
String deltaStr = field.substring(slashPos + 1);
|
||||||
|
ValueRange range = parseRange(rangeStr, type);
|
||||||
|
if (rangeStr.indexOf('-') == -1) {
|
||||||
|
range = ValueRange.of(range.getMinimum(), type.range().getMaximum());
|
||||||
|
}
|
||||||
|
int delta = Integer.parseInt(deltaStr);
|
||||||
|
if (delta <= 0) {
|
||||||
|
throw new IllegalArgumentException("Incrementer delta must be 1 or higher");
|
||||||
|
}
|
||||||
|
result.setBits(range, delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} catch (DateTimeException | IllegalArgumentException ex) {
|
||||||
|
String msg = ex.getMessage() + " '" + value + "'";
|
||||||
|
throw new IllegalArgumentException(msg, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ValueRange parseRange(String value, Type type) {
|
||||||
|
if (value.equals("*")) {
|
||||||
|
return type.range();
|
||||||
|
} else {
|
||||||
|
int hyphenPos = value.indexOf('-');
|
||||||
|
if (hyphenPos == -1) {
|
||||||
|
int result = type.checkValidValue(Integer.parseInt(value));
|
||||||
|
return ValueRange.of(result, result);
|
||||||
|
} else {
|
||||||
|
int min = Integer.parseInt(value, 0, hyphenPos, 10);
|
||||||
|
int max = Integer.parseInt(value, hyphenPos + 1, value.length(), 10);
|
||||||
|
min = type.checkValidValue(min);
|
||||||
|
max = type.checkValidValue(max);
|
||||||
|
if (type == Type.DAY_OF_WEEK && min == 7) {
|
||||||
|
// If used as a minimum in a range, Sunday means 0 (not 7)
|
||||||
|
min = 0;
|
||||||
|
}
|
||||||
|
return ValueRange.of(min, max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public <T extends Temporal & Comparable<? super T>> T nextOrSame(T temporal) {
|
||||||
|
int current = type().get(temporal);
|
||||||
|
int next = nextSetBit(current);
|
||||||
|
if (next == -1) {
|
||||||
|
temporal = type().rollForward(temporal);
|
||||||
|
next = nextSetBit(0);
|
||||||
|
}
|
||||||
|
if (next == current) {
|
||||||
|
return temporal;
|
||||||
|
} else {
|
||||||
|
int count = 0;
|
||||||
|
current = type().get(temporal);
|
||||||
|
while (current != next && count++ < CronExpression.MAX_ATTEMPTS) {
|
||||||
|
temporal = type().elapseUntil(temporal, next);
|
||||||
|
current = type().get(temporal);
|
||||||
|
next = nextSetBit(current);
|
||||||
|
if (next == -1) {
|
||||||
|
temporal = type().rollForward(temporal);
|
||||||
|
next = nextSetBit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (count >= CronExpression.MAX_ATTEMPTS) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return type().reset(temporal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean getBit(int index) {
|
||||||
|
return (this.bits & (1L << index)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int nextSetBit(int fromIndex) {
|
||||||
|
long result = this.bits & (MASK << fromIndex);
|
||||||
|
if (result != 0) {
|
||||||
|
return Long.numberOfTrailingZeros(result);
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setBits(ValueRange range) {
|
||||||
|
if (range.getMinimum() == range.getMaximum()) {
|
||||||
|
setBit((int) range.getMinimum());
|
||||||
|
} else {
|
||||||
|
long minMask = MASK << range.getMinimum();
|
||||||
|
long maxMask = MASK >>> -(range.getMaximum() + 1);
|
||||||
|
this.bits |= (minMask & maxMask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setBits(ValueRange range, int delta) {
|
||||||
|
if (delta == 1) {
|
||||||
|
setBits(range);
|
||||||
|
} else {
|
||||||
|
for (int i = (int) range.getMinimum(); i <= range.getMaximum(); i += delta) {
|
||||||
|
setBit(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setBit(int index) {
|
||||||
|
this.bits |= (1L << index);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearBit(int index) {
|
||||||
|
this.bits &= ~(1L << index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Long.hashCode(this.bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(@Nullable Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(o instanceof BitsCronField)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
BitsCronField other = (BitsCronField) o;
|
||||||
|
return type() == other.type() && this.bits == other.bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder builder = new StringBuilder(type().toString());
|
||||||
|
builder.append(" {");
|
||||||
|
int i = nextSetBit(0);
|
||||||
|
if (i != -1) {
|
||||||
|
builder.append(i);
|
||||||
|
i = nextSetBit(i + 1);
|
||||||
|
while (i != -1) {
|
||||||
|
builder.append(", ");
|
||||||
|
builder.append(i);
|
||||||
|
i = nextSetBit(i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
builder.append('}');
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class CompositeCronField extends CronField {
|
||||||
|
|
||||||
|
private final CronField[] fields;
|
||||||
|
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
private CompositeCronField(Type type, CronField[] fields, String value) {
|
||||||
|
super(type);
|
||||||
|
this.fields = fields;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CronField compose(CronField[] fields, Type type, String value) {
|
||||||
|
if (fields == null || fields.length < 1) {
|
||||||
|
throw new RedkaleException("Fields must not be empty");
|
||||||
|
}
|
||||||
|
if (Utility.isBlank(value)) {
|
||||||
|
throw new RedkaleException("Value must not be empty");
|
||||||
|
}
|
||||||
|
if (fields.length == 1) {
|
||||||
|
return fields[0];
|
||||||
|
} else {
|
||||||
|
return new CompositeCronField(type, fields, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public <T extends Temporal & Comparable<? super T>> T nextOrSame(T temporal) {
|
||||||
|
T result = null;
|
||||||
|
for (CronField field : this.fields) {
|
||||||
|
T candidate = field.nextOrSame(temporal);
|
||||||
|
if (result == null
|
||||||
|
|| candidate != null && candidate.compareTo(result) < 0) {
|
||||||
|
result = candidate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return this.value.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(@Nullable Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(o instanceof CompositeCronField)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
CompositeCronField other = (CompositeCronField) o;
|
||||||
|
return type() == other.type() && this.value.equals(other.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return type() + " '" + this.value + "'";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ package org.redkale.test.convert;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import org.junit.jupiter.api.*;
|
import org.junit.jupiter.api.*;
|
||||||
|
import org.redkale.convert.ConvertFactory;
|
||||||
import org.redkale.convert.json.*;
|
import org.redkale.convert.json.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -23,7 +24,7 @@ public class Json5Test {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void run1() throws Exception {
|
public void run1() throws Exception {
|
||||||
JsonFactory factory = JsonFactory.root().tiny(true).nullable(true);
|
JsonFactory factory = JsonFactory.root().features(ConvertFactory.FEATURE_TINY | ConvertFactory.FEATURE_NULLABLE);
|
||||||
final JsonConvert convert = factory.getConvert();
|
final JsonConvert convert = factory.getConvert();
|
||||||
Json5Bean bean = new Json5Bean();
|
Json5Bean bean = new Json5Bean();
|
||||||
bean.id = 60;
|
bean.id = 60;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import java.io.*;
|
|||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.junit.jupiter.api.*;
|
import org.junit.jupiter.api.*;
|
||||||
|
import org.redkale.convert.ConvertFactory;
|
||||||
import org.redkale.convert.json.*;
|
import org.redkale.convert.json.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -32,7 +33,7 @@ public class JsonMainTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void run1() throws Throwable {
|
public void run1() throws Throwable {
|
||||||
JsonFactory factory = JsonFactory.root().tiny(true);
|
JsonFactory factory = JsonFactory.root().features(ConvertFactory.FEATURE_TINY);
|
||||||
final JsonConvert convert = JsonConvert.root();
|
final JsonConvert convert = JsonConvert.root();
|
||||||
String json = "{\"access_token\":\"null\",\"priv\":null, vvv:nulla,\"priv2\":\"nulla\",\"expires_in\":7200, \"aa\":\"\"}";
|
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);
|
Map<String, String> map = convert.convertFrom(JsonConvert.TYPE_MAP_STRING_STRING, json);
|
||||||
@@ -53,7 +54,7 @@ public class JsonMainTest {
|
|||||||
SimpleChildEntity entry = SimpleChildEntity.create();
|
SimpleChildEntity entry = SimpleChildEntity.create();
|
||||||
String json = convert.convertTo(SimpleEntity.class, entry);
|
String json = convert.convertTo(SimpleEntity.class, entry);
|
||||||
System.out.println("长度: " + json.length());
|
System.out.println("长度: " + json.length());
|
||||||
JsonByteBufferWriter writer = new JsonByteBufferWriter(false, false, () -> ByteBuffer.allocate(1)) {
|
JsonByteBufferWriter writer = new JsonByteBufferWriter(0, () -> ByteBuffer.allocate(1)) {
|
||||||
};
|
};
|
||||||
convert.convertTo(writer, SimpleEntity.class, entry);
|
convert.convertTo(writer, SimpleEntity.class, entry);
|
||||||
ByteBuffer[] buffers = writer.toBuffers();
|
ByteBuffer[] buffers = writer.toBuffers();
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
package org.redkale.test.convert;
|
package org.redkale.test.convert;
|
||||||
|
|
||||||
import org.junit.jupiter.api.*;
|
import org.junit.jupiter.api.*;
|
||||||
|
import org.redkale.convert.ConvertFactory;
|
||||||
import org.redkale.convert.json.*;
|
import org.redkale.convert.json.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -24,17 +25,21 @@ public class TinyTest {
|
|||||||
TinyRecord record = new TinyRecord();
|
TinyRecord record = new TinyRecord();
|
||||||
record.id = 5;
|
record.id = 5;
|
||||||
{
|
{
|
||||||
JsonFactory factory = JsonFactory.create().tiny(true);
|
JsonFactory factory = JsonFactory.create().features(ConvertFactory.FEATURE_TINY);
|
||||||
JsonConvert convert = factory.getConvert();
|
JsonConvert convert = factory.getConvert();
|
||||||
String json = "{\"id\":5}";
|
String json = "{\"id\":5}";
|
||||||
if (!main) Assertions.assertEquals(json, convert.convertTo(record));
|
if (!main) {
|
||||||
|
Assertions.assertEquals(json, convert.convertTo(record));
|
||||||
|
}
|
||||||
System.out.println(convert.convertTo(record));
|
System.out.println(convert.convertTo(record));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
JsonFactory factory = JsonFactory.create().tiny(false);
|
JsonFactory factory = JsonFactory.create().features(0);
|
||||||
JsonConvert convert = factory.getConvert();
|
JsonConvert convert = factory.getConvert();
|
||||||
String json = "{\"id\":5,\"name\":\"\"}";
|
String json = "{\"id\":5,\"name\":\"\"}";
|
||||||
if (!main) Assertions.assertEquals(json, convert.convertTo(record));
|
if (!main) {
|
||||||
|
Assertions.assertEquals(json, convert.convertTo(record));
|
||||||
|
}
|
||||||
System.out.println(convert.convertTo(record));
|
System.out.println(convert.convertTo(record));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user