Skip to content

Commit

Permalink
improved JSONField(format=xxxx) support
Browse files Browse the repository at this point in the history
  • Loading branch information
wenshao committed May 5, 2016
1 parent 3b0d349 commit 2541a48
Show file tree
Hide file tree
Showing 12 changed files with 133 additions and 26 deletions.
Expand Up @@ -64,6 +64,7 @@
import com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer;
import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
import com.alibaba.fastjson.parser.deserializer.ResolveFieldDeserializer;
import com.alibaba.fastjson.serializer.BeanContext;
import com.alibaba.fastjson.serializer.IntegerCodec;
import com.alibaba.fastjson.serializer.LongCodec;
import com.alibaba.fastjson.serializer.StringCodec;
Expand Down Expand Up @@ -101,6 +102,8 @@ public class DefaultJSONParser implements Closeable {
private List<ExtraTypeProvider> extraTypeProviders = null;
private List<ExtraProcessor> extraProcessors = null;
protected FieldTypeResolver fieldTypeResolver = null;

protected transient BeanContext lastBeanContext;

static {
primitiveClasses.add(boolean.class);
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/com/alibaba/fastjson/parser/ParserConfig.java
Expand Up @@ -518,7 +518,9 @@ public ObjectDeserializer createJavaBeanDeserializer(Class<?> clazz, Type type)
}

JSONField annotation = fieldInfo.getAnnotation();
if (annotation != null && !ASMUtils.checkName(annotation.name())) {
if (annotation != null //
&& ((!ASMUtils.checkName(annotation.name())) //
|| annotation.format().length() != 0)) {
asmEnable = false;
break;
}
Expand Down
@@ -0,0 +1,13 @@
package com.alibaba.fastjson.parser.deserializer;

import java.lang.reflect.Type;

import com.alibaba.fastjson.parser.DefaultJSONParser;

public abstract class ContextObjectDeserializer implements ObjectDeserializer {
public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
return deserialze(parser, type, fieldName, null, 0);
}

public abstract <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName, String format, int features);
}
Expand Up @@ -38,12 +38,20 @@ public void parseField(DefaultJSONParser parser, Object object, Type objectType,
objContext.type = objectType;
}

// ContextObjectDeserializer
Object value;
if (fieldValueDeserilizer instanceof JavaBeanDeserializer) {
JavaBeanDeserializer javaBeanDeser = (JavaBeanDeserializer) fieldValueDeserilizer;
value = javaBeanDeser.deserialze(parser, fieldInfo.fieldType, fieldInfo.name, fieldInfo.parserFeatures);
} else {
value = fieldValueDeserilizer.deserialze(parser, fieldInfo.fieldType, fieldInfo.name);
if (this.fieldInfo.format != null
&& fieldValueDeserilizer instanceof ContextObjectDeserializer
) {
value = ((ContextObjectDeserializer)fieldValueDeserilizer) //
.deserialze(parser, fieldInfo.fieldType, fieldInfo.name, fieldInfo.format, fieldInfo.parserFeatures);
} else {
value = fieldValueDeserilizer.deserialze(parser, fieldInfo.fieldType, fieldInfo.name);
}
}
if (parser.getResolveStatus() == DefaultJSONParser.NeedToResolve) {
ResolveTask task = parser.getLastResolveTask();
Expand Down
Expand Up @@ -11,13 +11,16 @@

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.parser.DefaultJSONParser;
import com.alibaba.fastjson.serializer.BeanContext;
import com.alibaba.fastjson.util.FieldInfo;

public abstract class FieldDeserializer {

public final FieldInfo fieldInfo;

protected final Class<?> clazz;

protected BeanContext beanContext;

public FieldDeserializer(Class<?> clazz, FieldInfo fieldInfo){
this.clazz = clazz;
Expand Down
Expand Up @@ -12,32 +12,45 @@
import java.time.Period;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;

import com.alibaba.fastjson.parser.DefaultJSONParser;
import com.alibaba.fastjson.parser.JSONLexer;
import com.alibaba.fastjson.parser.JSONToken;
import com.alibaba.fastjson.serializer.BeanContext;
import com.alibaba.fastjson.serializer.ContextObjectSerializer;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import com.alibaba.fastjson.serializer.SerializeWriter;

public class Jdk8DateCodec implements ObjectSerializer, ObjectDeserializer {
public class Jdk8DateCodec extends ContextObjectDeserializer implements ObjectSerializer, ContextObjectSerializer, ObjectDeserializer {

public static final Jdk8DateCodec instance = new Jdk8DateCodec();

@SuppressWarnings("unchecked")
public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName, String format, int feature) {
JSONLexer lexer = parser.lexer;
if (lexer.token() == JSONToken.LITERAL_STRING) {
String text = lexer.stringVal();
lexer.nextToken();

DateTimeFormatter formatter = null;
if (format != null) {
formatter = DateTimeFormatter.ofPattern(format);
}

if (type == LocalDateTime.class) {
LocalDateTime localDateTime;
if (text.length() == 10) {
LocalDate localDate = LocalDate.parse(text);
if (text.length() == 10 || text.length() == 8) {
LocalDate localDate = formatter == null ? //
LocalDate.parse(text) //
: LocalDate.parse(text, formatter);
localDateTime = LocalDateTime.of(localDate, LocalTime.MIN);
} else {
localDateTime = LocalDateTime.parse(text);
localDateTime = formatter == null ? //
LocalDateTime.parse(text) //
: LocalDateTime.parse(text, formatter);
}
return (T) localDateTime;
} else if (type == LocalDate.class) {
Expand Down Expand Up @@ -107,4 +120,12 @@ public void write(JSONSerializer serializer, Object object, Object fieldName, Ty
}
}

@Override
public void write(JSONSerializer serializer, Object object, BeanContext context) throws IOException {
SerializeWriter out = serializer.out;
String format = context.getFormat();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
String text = formatter.format((TemporalAccessor) object);
out.writeString(text);
}
}
Expand Up @@ -15,10 +15,12 @@ public final class BeanContext {

private final Class<?> beanClass;
private final FieldInfo fieldInfo;
private final String format;

BeanContext(Class<?> beanClass, FieldInfo fieldInfo){
public BeanContext(Class<?> beanClass, FieldInfo fieldInfo){
this.beanClass = beanClass;
this.fieldInfo = fieldInfo;
this.format = fieldInfo.getFormat();
}

public Class<?> getBeanClass() {
Expand Down Expand Up @@ -56,4 +58,8 @@ public int getFeatures() {
public <T extends Annotation> T getAnnation(Class<T> annotationClass) {
return fieldInfo.getAnnation(annotationClass);
}

public String getFormat() {
return format;
}
}
@@ -0,0 +1,9 @@
package com.alibaba.fastjson.serializer;

import java.io.IOException;

public interface ContextObjectSerializer extends ObjectSerializer {
void write(JSONSerializer serializer, //
Object object, //
BeanContext context) throws IOException;
}
Expand Up @@ -111,11 +111,6 @@ public int compareTo(FieldSerializer o) {


public void writeValue(JSONSerializer serializer, Object propertyValue) throws Exception {
if (format != null) {
serializer.writeWithFormat(propertyValue, format);
return;
}

if (runtimeInfo == null) {

Class<?> runtimeFieldClass;
Expand Down Expand Up @@ -182,8 +177,15 @@ public void writeValue(JSONSerializer serializer, Object propertyValue) throws E
valueSerializer = serializer.getObjectWriter(valueClass);
}

valueSerializer.write(serializer, propertyValue, fieldInfo.name, fieldInfo.fieldType, fieldFeatures);

if (format != null) {
if (valueSerializer instanceof ContextObjectSerializer) {
((ContextObjectSerializer) valueSerializer).write(serializer, propertyValue, this.fieldContext);
} else {
serializer.writeWithFormat(propertyValue, format);
}
} else {
valueSerializer.write(serializer, propertyValue, fieldInfo.name, fieldInfo.fieldType, fieldFeatures);
}

}

Expand Down
Expand Up @@ -140,7 +140,9 @@ public ObjectSerializer createJavaBeanSerializer(SerializeBeanInfo beanInfo) {
if (asm) {
for(Field field : clazz.getDeclaredFields()){
JSONField annotation = field.getAnnotation(JSONField.class);
if (annotation != null && !ASMUtils.checkName(annotation.name())) {
if (annotation != null //
&& ((!ASMUtils.checkName(annotation.name())) //
|| annotation.format().length() != 0)) {
asm = false;
break;
}
Expand Down
25 changes: 15 additions & 10 deletions src/main/java/com/alibaba/fastjson/util/FieldInfo.java
Expand Up @@ -40,6 +40,8 @@ public class FieldInfo implements Comparable<FieldInfo> {

public final boolean isEnum;

public final String format;

public FieldInfo(String name, //
Class<?> declaringClass, //
Class<?> fieldClass, //
Expand Down Expand Up @@ -79,6 +81,7 @@ public FieldInfo(String name, //
fieldAnnotation = null;
methodAnnotation = null;
this.getOnly = false;
this.format = null;
}

public FieldInfo(String name, //
Expand Down Expand Up @@ -123,6 +126,18 @@ public FieldInfo(String name, //
this.label = "";
}

String format = null;
JSONField annotation = getAnnotation();

if (annotation != null) {
format = annotation.format();

if (format.trim().length() == 0) {
format = null;
}
}
this.format = format;

name_chars = genFieldNameChars();

if (method != null) {
Expand Down Expand Up @@ -403,16 +418,6 @@ public JSONField getAnnotation() {
}

public String getFormat() {
String format = null;
JSONField annotation = getAnnotation();

if (annotation != null) {
format = annotation.format();

if (format.trim().length() == 0) {
format = null;
}
}
return format;
}

Expand Down
33 changes: 33 additions & 0 deletions src/test/java/com/alibaba/json/bvt/jdk8/LocalDateTimeTest3.java
@@ -0,0 +1,33 @@
package com.alibaba.json.bvt.jdk8;

import java.time.LocalDateTime;

import org.junit.Assert;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;

import junit.framework.TestCase;

public class LocalDateTimeTest3 extends TestCase {

public void test_for_issue() throws Exception {
String text = "{\"date\":\"20111203\"}";
VO vo = JSON.parseObject(text, VO.class);

Assert.assertEquals(2011, vo.date.getYear());
Assert.assertEquals(12, vo.date.getMonthValue());
Assert.assertEquals(03, vo.date.getDayOfMonth());
Assert.assertEquals(0, vo.date.getHour());
Assert.assertEquals(0, vo.date.getMinute());
Assert.assertEquals(0, vo.date.getSecond());

Assert.assertEquals(text, JSON.toJSONString(vo));
}

private static class VO {
@JSONField(format="yyyyMMdd")
public LocalDateTime date;

}
}

0 comments on commit 2541a48

Please sign in to comment.