Skip to content

Commit

Permalink
support ContextValueFilter, for issue #484
Browse files Browse the repository at this point in the history
  • Loading branch information
wenshao committed Jun 17, 2022
1 parent 14c6cc0 commit 34cdbf7
Show file tree
Hide file tree
Showing 9 changed files with 295 additions and 17 deletions.
40 changes: 33 additions & 7 deletions core/src/main/java/com/alibaba/fastjson2/JSONWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,8 @@ public boolean hasFilter() {
|| context.valueFilter != null
|| context.beforeFilter != null
|| context.afterFilter != null
|| context.labelFilter != null;
|| context.labelFilter != null
|| context.contextValueFilter != null;
}

public boolean isWriteNulls() {
Expand Down Expand Up @@ -1160,6 +1161,7 @@ public static class Context {
BeforeFilter beforeFilter;
AfterFilter afterFilter;
LabelFilter labelFilter;
ContextValueFilter contextValueFilter;

public Context(ObjectWriterProvider provider) {
if (provider == null) {
Expand Down Expand Up @@ -1213,19 +1215,35 @@ protected void configFilter(Filter... filters) {
for (Filter filter : filters) {
if (filter instanceof NameFilter) {
this.nameFilter = (NameFilter) filter;
} else if (filter instanceof ValueFilter) {
}

if (filter instanceof ValueFilter) {
this.valueFilter = (ValueFilter) filter;
} else if (filter instanceof PropertyFilter) {
}

if (filter instanceof PropertyFilter) {
this.propertyFilter = (PropertyFilter) filter;
} else if (filter instanceof PropertyPreFilter) {
}

if (filter instanceof PropertyPreFilter) {
this.propertyPreFilter = (PropertyPreFilter) filter;
} else if (filter instanceof BeforeFilter) {
}

if (filter instanceof BeforeFilter) {
this.beforeFilter = (BeforeFilter) filter;
} else if (filter instanceof AfterFilter) {
}

if (filter instanceof AfterFilter) {
this.afterFilter = (AfterFilter) filter;
} else if (filter instanceof LabelFilter) {
}

if (filter instanceof LabelFilter) {
this.labelFilter = (LabelFilter) filter;
}

if (filter instanceof ContextValueFilter) {
this.contextValueFilter = (ContextValueFilter) filter;
}
}
}

Expand Down Expand Up @@ -1362,6 +1380,14 @@ public void setValueFilter(ValueFilter valueFilter) {
this.valueFilter = valueFilter;
}

public ContextValueFilter getContextValueFilter() {
return contextValueFilter;
}

public void setContextValueFilter(ContextValueFilter contextValueFilter) {
this.contextValueFilter = contextValueFilter;
}

public PropertyFilter getPropertyFilter() {
return propertyFilter;
}
Expand Down
101 changes: 101 additions & 0 deletions core/src/main/java/com/alibaba/fastjson2/filter/BeanContext.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package com.alibaba.fastjson2.filter;

import com.alibaba.fastjson2.codec.FieldInfo;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;

public class BeanContext {
private final Class beanClass;

private final Method method;

private final Field field;

private final String name;

private final String label;

private final Class fieldClass;
private final Type fieldType;

private final long features;

private final String format;

public BeanContext(
Class beanClass,
Method method,
Field field,
String name,
String label,
Class fieldClass,
Type fieldType,
long features,
String format) {
this.beanClass = beanClass;
this.method = method;
this.field = field;
this.name = name;
this.label = label;
this.fieldClass = fieldClass;
this.fieldType = fieldType;
this.features = features;
this.format = format;
}

public Class<?> getBeanClass() {
return beanClass;
}

public Method getMethod() {
return method;
}

public Field getField() {
return field;
}

public String getName() {
return name;
}

public String getLabel() {
return label;
}

public Class<?> getFieldClass() {
return fieldClass;
}

public Type getFieldType() {
return fieldType;
}

public long getFeatures() {
return features;
}

public boolean isJsonDirect() {
return (features & FieldInfo.RAW_VALUE_MASK) != 0;
}

public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
T annotatition = null;
if (method != null) {
annotatition = method.getAnnotation(annotationClass);
}

if (annotatition == null && field != null) {
annotatition = field.getAnnotation(annotationClass);
}

return annotatition;
}

public String getFormat() {
return format;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.alibaba.fastjson2.filter;

public interface ContextValueFilter
extends Filter {
Object process(BeanContext context, Object object, String name, Object value);
}
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ public void writeWithFilter(JSONWriter jsonWriter, Object object, Object fieldNa
PropertyPreFilter propertyPreFilter = context.getPropertyPreFilter();
NameFilter nameFilter = context.getNameFilter();
ValueFilter valueFilter = context.getValueFilter();
ContextValueFilter contextValueFilter = context.getContextValueFilter();
PropertyFilter propertyFilter = context.getPropertyFilter();
LabelFilter labelFilter = context.getLabelFilter();

Expand All @@ -372,7 +373,7 @@ public void writeWithFilter(JSONWriter jsonWriter, Object object, Object fieldNa
}

// fast return
if (nameFilter == null && propertyFilter == null && valueFilter == null) {
if (nameFilter == null && propertyFilter == null && valueFilter == null && contextValueFilter == null) {
fieldWriter.write(jsonWriter, object);
continue;
}
Expand All @@ -396,9 +397,26 @@ public void writeWithFilter(JSONWriter jsonWriter, Object object, Object fieldNa

boolean nameChanged = filteredName != null && filteredName != fieldName;

Object filteredValue;
if (valueFilter != null
&& (filteredValue = valueFilter.apply(object, fieldWriterFieldName, fieldValue)) != fieldValue) {
Object filteredValue = fieldValue;
if (valueFilter != null) {
filteredValue = valueFilter.apply(object, fieldWriterFieldName, fieldValue);
}
if (contextValueFilter != null) {
BeanContext beanContext = new BeanContext(
objectType,
fieldWriter.getMethod(),
fieldWriter.getField(),
fieldWriter.getFieldName(),
fieldWriter.getLabel(),
fieldWriter.getFieldClass(),
fieldWriter.getFieldType(),
fieldWriter.getFeatures(),
fieldWriter.getFormat()
);
filteredValue = contextValueFilter.process(beanContext, object, filteredName, filteredValue);
}

if (filteredValue != fieldValue) {
if (nameChanged) {
jsonWriter.writeName(filteredName);
jsonWriter.writeColon();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.alibaba.fastjson2.filter;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.annotation.JSONField;
import org.junit.jupiter.api.Test;

import java.util.concurrent.atomic.AtomicReference;

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

public class ContextValueFilterTest {
@Test
public void test() throws Exception {
Bean bean = new Bean();
bean.id = 10;

AtomicReference<BeanContext> contextReference = new AtomicReference<>();

ContextValueFilter filter = (BeanContext context, Object object, String name, Object value) -> {
contextReference.set(context);
return value;
};

JSON.toJSONString(bean, filter);

BeanContext context = contextReference.get();
assertEquals(Bean.class, context.getBeanClass());
assertEquals(int.class, context.getFieldClass());
assertEquals(int.class, context.getFieldType());
assertEquals(Bean.class.getField("id"), context.getField());
assertEquals("userId", context.getAnnotation(JSONField.class).name());
assertEquals(null, context.getFormat());
assertEquals(null, context.getLabel());
assertEquals(0, context.getFeatures());
}

public static class Bean {
@JSONField(name = "userId")
public int id;
}
}
28 changes: 22 additions & 6 deletions fastjson1-compatible/src/main/java/com/alibaba/fastjson/JSON.java
Original file line number Diff line number Diff line change
Expand Up @@ -608,19 +608,35 @@ public static void configFilter(JSONWriter.Context context, SerializeFilter... f
static void configFilter(JSONWriter.Context context, SerializeFilter filter) {
if (filter instanceof NameFilter) {
context.setNameFilter((NameFilter) filter);
} else if (filter instanceof ValueFilter) {
}

if (filter instanceof ValueFilter) {
context.setValueFilter((ValueFilter) filter);
} else if (filter instanceof PropertyPreFilter) {
}

if (filter instanceof PropertyPreFilter) {
context.setPropertyPreFilter((PropertyPreFilter) filter);
} else if (filter instanceof PropertyFilter) {
}

if (filter instanceof PropertyFilter) {
context.setPropertyFilter((PropertyFilter) filter);
} else if (filter instanceof BeforeFilter) {
}

if (filter instanceof BeforeFilter) {
context.setBeforeFilter((BeforeFilter) filter);
} else if (filter instanceof AfterFilter) {
}

if (filter instanceof AfterFilter) {
context.setAfterFilter((AfterFilter) filter);
} else if (filter instanceof LabelFilter) {
}

if (filter instanceof LabelFilter) {
context.setLabelFilter((LabelFilter) filter);
}

if (filter instanceof ContextValueFilter) {
context.setContextValueFilter((ContextValueFilter) filter);
}
}

public static byte[] toJSONBytes(Object object, SerializeFilter[] filters, SerializerFeature... features) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.alibaba.fastjson.serializer;

public class BeanContext
extends com.alibaba.fastjson2.filter.BeanContext {
public BeanContext(com.alibaba.fastjson2.filter.BeanContext ctx) {
super(
ctx.getBeanClass(),
ctx.getMethod(),
ctx.getField(),
ctx.getName(),
ctx.getLabel(),
ctx.getFieldClass(),
ctx.getFieldType(),
ctx.getFeatures(),
ctx.getFormat()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.alibaba.fastjson.serializer;

public interface ContextValueFilter
extends com.alibaba.fastjson2.filter.ContextValueFilter, SerializeFilter {
default Object process(com.alibaba.fastjson2.filter.BeanContext context, Object object, String name, Object value) {
return process(new com.alibaba.fastjson.serializer.BeanContext(context), object, name, value);
}

Object process(BeanContext context, Object object, String name, Object value);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.alibaba.fastjson;

import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.serializer.BeanContext;
import com.alibaba.fastjson.serializer.ContextValueFilter;
import org.junit.jupiter.api.Test;

import java.util.concurrent.atomic.AtomicReference;

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

public class ContextValueFilterTest {
@Test
public void test() throws Exception {
Bean bean = new Bean();
bean.id = 10;

AtomicReference<BeanContext> contextReference = new AtomicReference<>();

ContextValueFilter filter = (BeanContext context, Object object, String name, Object value) -> {
contextReference.set(context);
return value;
};

JSON.toJSONString(bean, filter);

BeanContext context = contextReference.get();
assertEquals(Bean.class, context.getBeanClass());
assertEquals(int.class, context.getFieldClass());
assertEquals(int.class, context.getFieldType());
assertEquals(Bean.class.getField("id"), context.getField());
assertEquals("userId", context.getAnnotation(JSONField.class).name());
assertEquals(null, context.getFormat());
assertEquals(null, context.getLabel());
assertEquals(0, context.getFeatures());
}

public static class Bean {
@JSONField(name = "userId")
public int id;
}
}

0 comments on commit 34cdbf7

Please sign in to comment.