Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/alibaba/fastjson2 into main
Browse files Browse the repository at this point in the history
  • Loading branch information
VictorZeng committed May 31, 2022
2 parents ade07e9 + 75e25bc commit 6a1bbbc
Show file tree
Hide file tree
Showing 20 changed files with 417 additions and 24 deletions.
26 changes: 26 additions & 0 deletions core/src/main/java/com/alibaba/fastjson2/JSON.java
Original file line number Diff line number Diff line change
Expand Up @@ -1395,6 +1395,7 @@ static <T> List<T> parseArray(byte[] bytes, Type type, JSONReader.Feature... fea
return list;
}
}

/**
* Parse UTF8 encoded JSON byte array into {@link List} with specified {@link JSONReader.Feature}s enabled
*
Expand All @@ -1417,6 +1418,31 @@ static <T> List<T> parseArray(byte[] bytes, Class<T> type, JSONReader.Feature...
}
}

/**
* Parse UTF8 encoded JSON byte array into {@link List} with specified {@link JSONReader.Feature}s enabled
*
* @param bytes UTF8 encoded JSON byte array to parse
* @param offset the index of the first byte to validate
* @param length the number of bytes to validate
* @param charset specify {@link Charset} to validate
* @param type specify the {@link Class} to be converted
* @param features features to be enabled in parsing
*/
static <T> List<T> parseArray(byte[] bytes, int offset, int length, Charset charset, Class<T> type, JSONReader.Feature... features) {
if (bytes == null || bytes.length == 0) {
return null;
}

try (JSONReader reader = JSONReader.of(bytes, offset, length, charset)) {
reader.context.config(features);
List<T> list = reader.readArray(type);
if (reader.resolveTasks != null) {
reader.handleResolveTasks(list);
}
return list;
}
}

/**
* Serialize Java Object to JSON {@link String}
*
Expand Down
4 changes: 4 additions & 0 deletions core/src/main/java/com/alibaba/fastjson2/JSONB.java
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,10 @@ static <T> T parseObject(
}
}

static <T> T parseObject(byte[] jsonbBytes, TypeReference typeReference, JSONReader.Feature... features) {
return parseObject(jsonbBytes, typeReference.getType(), features);
}

static <T> T parseObject(byte[] jsonbBytes, Class<T> objectClass, JSONReader.Feature... features) {
ObjectReaderProvider provider = JSONFactory.getDefaultObjectReaderProvider();
JSONReader.Context ctx = new JSONReader.Context(provider);
Expand Down
3 changes: 2 additions & 1 deletion core/src/main/java/com/alibaba/fastjson2/JSONReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -2428,7 +2428,8 @@ public enum Feature {
ErrorOnEnumNotMatch(1 << 12),
TrimString(1 << 13),
ErrorOnNotSupportAutoType(1 << 14),
DuplicateKeyValueAsArray(1 << 15);
DuplicateKeyValueAsArray(1 << 15),
AllowUnQuotedFieldNames(1 << 16);

public final long mask;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,13 @@ public boolean nextIfMatch(char ch) {
@Override
public long readFieldNameHashCode() {
if (ch != '"' && ch != '\'') {
return -1;
if ((context.features & Feature.AllowUnQuotedFieldNames.mask) != 0) {
return readFieldNameHashCodeUnquote();
}
if (ch == '}' || isNull()) {
return -1;
}
throw new JSONException("illegal character " + ch);
}

final char quote = ch;
Expand Down
19 changes: 17 additions & 2 deletions core/src/main/java/com/alibaba/fastjson2/JSONReaderStr.java
Original file line number Diff line number Diff line change
Expand Up @@ -210,13 +210,28 @@ public long readFieldNameHashCodeUnquote() {
: str.charAt(offset++);
}

if (ch == ':') {
ch = str.charAt(offset++);

while (ch <= ' ' && ((1L << ch) & SPACE) != 0) {
offset++;
ch = str.charAt(offset);
}
}

return hashCode;
}

@Override
public long readFieldNameHashCode() {
if (ch != '"' && ch != '\'') {
return -1;
if ((context.features & Feature.AllowUnQuotedFieldNames.mask) != 0) {
return readFieldNameHashCodeUnquote();
}
if (ch == '}' || isNull()) {
return -1;
}
throw new JSONException("illegal character " + ch);
}

final char quote = ch;
Expand Down Expand Up @@ -3534,7 +3549,7 @@ protected ZonedDateTime readZonedDateTimeX(int len) {

@Override
protected LocalDateTime readLocalDateTime19() {
if (ch != '"') {
if (ch != '"' && ch != '\'') {
throw new JSONException("date only support string input");
}

Expand Down
19 changes: 17 additions & 2 deletions core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16.java
Original file line number Diff line number Diff line change
Expand Up @@ -397,13 +397,28 @@ public long readFieldNameHashCodeUnquote() {
: chars[offset++];
}

if (ch == ':') {
ch = chars[offset++];

while (ch <= ' ' && ((1L << ch) & SPACE) != 0) {
offset++;
ch = chars[offset];
}
}

return hashCode;
}

@Override
public long readFieldNameHashCode() {
if (ch != '"' && ch != '\'') {
return -1;
if ((context.features & Feature.AllowUnQuotedFieldNames.mask) != 0) {
return readFieldNameHashCodeUnquote();
}
if (ch == '}' || isNull()) {
return -1;
}
throw new JSONException("illegal character " + ch);
}

final char quote = ch;
Expand Down Expand Up @@ -3781,7 +3796,7 @@ protected ZonedDateTime readZonedDateTimeX(int len) {

@Override
protected LocalDateTime readLocalDateTime19() {
if (ch != '"') {
if (ch != '"' && ch != '\'') {
throw new JSONException("date only support string input");
}

Expand Down
19 changes: 17 additions & 2 deletions core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,15 @@ public long readFieldNameHashCodeUnquote() {
: (char) bytes[offset++];
}

if (ch == ':') {
ch = (char) bytes[offset++];

while (ch <= ' ' && ((1L << ch) & SPACE) != 0) {
offset++;
ch = (char) bytes[offset];
}
}

return hashCode;
}

Expand Down Expand Up @@ -360,7 +369,13 @@ public long readFieldNameHashCodeUnquote1() {
@Override
public long readFieldNameHashCode() {
if (ch != '"' && ch != '\'') {
return -1;
if ((context.features & Feature.AllowUnQuotedFieldNames.mask) != 0) {
return readFieldNameHashCodeUnquote();
}
if (ch == '}' || isNull()) {
return -1;
}
throw new JSONException("illegal character " + ch);
}

final char quote = ch;
Expand Down Expand Up @@ -4779,7 +4794,7 @@ protected LocalDateTime readLocalDateTime18() {

@Override
protected LocalDateTime readLocalDateTime19() {
if (ch != '"') {
if (ch != '"' && ch != '\'') {
throw new JSONException("date only support string input");
}

Expand Down
13 changes: 13 additions & 0 deletions core/src/main/java/com/alibaba/fastjson2/annotation/JSONField.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,21 @@
* Specifies that {@link com.alibaba.fastjson2.writer.ObjectWriter} is used when serializing
*/
@SuppressWarnings("rawtypes")
@Deprecated
Class writeUsing() default Void.class;

/**
* Specifies that {@link com.alibaba.fastjson2.writer.ObjectWriter} is used when serializing
*/
@SuppressWarnings("rawtypes")
Class serializeUsing() default Void.class;

/**
* Specifies that {@link com.alibaba.fastjson2.writer.ObjectWriter} is used when serializing
*/
@SuppressWarnings("rawtypes")
Class deserializeUsing() default Void.class;

/**
* Specify {@link JSONReader.Feature}s to use features when deserializing
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,11 @@ private void getFieldInfo(FieldInfo fieldInfo, JSONField jsonField) {
if (!schema.isEmpty()) {
fieldInfo.schema = schema;
}

Class deserializeUsing = jsonField.deserializeUsing();
if (ObjectReader.class.isAssignableFrom(deserializeUsing)) {
fieldInfo.readUsing = deserializeUsing;
}
}
}

Expand Down Expand Up @@ -1366,7 +1371,7 @@ public ObjectReader getObjectReader(ObjectReaderProvider provider, Type type) {
return ObjectReaderImplList.of(type, null, 0);
}

if (type == Set.class || type == AbstractSet.class) {
if (type == Set.class || type == AbstractSet.class || type == EnumSet.class) {
// return new ObjectReaderImplList(type, (Class) type, HashSet.class, Object.class, null);
return ObjectReaderImplList.of(type, null, 0);
}
Expand Down Expand Up @@ -1550,7 +1555,7 @@ public ObjectReader getObjectReader(ObjectReaderProvider provider, Type type) {
}
}

if (rawType == Set.class || rawType == AbstractSet.class) {
if (rawType == Set.class || rawType == AbstractSet.class || rawType == EnumSet.class) {
if (itemClass == String.class) {
return new ObjectReaderImplListStr((Class) rawType, HashSet.class);
} else if (itemClass == Long.class) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ public static ObjectReader of(Type type, Class listClass, long features) {
instanceClass = LinkedList.class;
} else if (listClass == Set.class || listClass == AbstractSet.class) {
instanceClass = HashSet.class;
} else if (listClass == EnumSet.class) {
instanceClass = HashSet.class;
builder = (o) -> EnumSet.copyOf((Collection) o);
} else if (listClass == NavigableSet.class || listClass == SortedSet.class) {
instanceClass = TreeSet.class;
} else if (listClass == CLASS_SINGLETON) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,11 @@ public void getFieldInfo(BeanInfo beanInfo, FieldInfo fieldInfo, Class objectTyp
if (ObjectWriter.class.isAssignableFrom(writeUsing)) {
fieldInfo.writeUsing = writeUsing;
}

Class serializeUsing = jsonField.serializeUsing();
if (ObjectWriter.class.isAssignableFrom(serializeUsing)) {
fieldInfo.writeUsing = serializeUsing;
}
}

private void processJacksonJsonProperty(FieldInfo fieldInfo, Annotation annotation) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ public void test_0() {
reader.readFieldNameHashCodeUnquote()
);

assertTrue(
reader.nextIfMatch(':')
);

assertEquals(123,
reader.readInt32()
.intValue());
Expand Down
50 changes: 50 additions & 0 deletions core/src/test/java/com/alibaba/fastjson2/annotation/UsingTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.alibaba.fastjson2.annotation;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.reader.ObjectReader;
import com.alibaba.fastjson2.writer.ObjectWriter;
import org.junit.jupiter.api.Test;

import java.lang.reflect.Type;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class UsingTest {
@Test
public void test() {
Bean bean = new Bean();
bean.id = 123;

String str = JSON.toJSONString(bean);
assertEquals("{\"id\":\"123元\"}", str);

Bean bean1 = JSON.parseObject(str, Bean.class);
assertEquals(bean.id, bean1.id);
}

public static class Bean {
@JSONField(serializeUsing = IdCodec.class, deserializeUsing = IdCodec.class)
public int id;
}

public static class IdCodec
implements ObjectReader, ObjectWriter {
public long getFeatures() {
return 0;
}

@Override
public Object readObject(JSONReader jsonReader, long features) {
String str = jsonReader.readString();
str = str.replace("元", "");
return Integer.parseInt(str);
}

@Override
public void write(JSONWriter jsonWriter, Object object, Object fieldName, Type fieldType, long features) {
jsonWriter.writeString(object.toString() + "元");
}
}
}
Loading

0 comments on commit 6a1bbbc

Please sign in to comment.