package com.alibaba.json.bvt.serializer.filters; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.serializer.JSONSerializer; import com.alibaba.fastjson.serializer.PropertyPreFilter; import com.alibaba.fastjson.serializer.SerialContext; import junit.framework.TestCase; import org.junit.Assert; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class PropertyPathTest3 extends TestCase { /** 测试只输出子集合中的特定属性 */ public void test_path() throws Exception { Person p1 = new Person(); p1.setId(100); Person c1 = new Person(); c1.setId(1000); Person c2 = new Person(); c2.setId(2000); p1.getChildren().add(c1); p1.getChildren().add(c2); //只输出children.id以及根上的id String s = JSON.toJSONString(p1, new MyPropertyPreFilter(new String[] {"children.id", "id"})); Assert.assertEquals("{\"children\":[{\"id\":1000},{\"id\":2000}],\"id\":100}", s); } /** 测试只输出子字段map中的特定属性 */ public void test_path2() throws Exception { Person2 p1 = new Person2(); p1.setId(1); Map<String, String> infoMap = new HashMap<String, String>(); infoMap.put("name", "李三"); infoMap.put("height", "168"); p1.setInfoMap(infoMap); //只输出infoMap.name String s = JSON.toJSONString(p1, new MyPropertyPreFilter(new String[] {"infoMap.name"})); Assert.assertEquals("{\"infoMap\":{\"name\":\"李三\"}}", s); } public static class MyPropertyPreFilter implements PropertyPreFilter { String[] onlyProperties; public MyPropertyPreFilter(String[] onlyProperties) { this.onlyProperties = onlyProperties; } private static boolean containInclude(String[] ss, String s) { if(ss == null || ss.length == 0 || s == null) return false; for(String st : ss) if(st.startsWith(s)) return true; return false; } public boolean apply(JSONSerializer serializer, Object source, String name) { SerialContext nowContext = new SerialContext(serializer.getContext(), source, name, 0, 0); String nowPath = getLinkedPath(nowContext); System.out.println("path->" + nowPath); //只输出children.id return containInclude(onlyProperties, nowPath); } } /** 输出结果 类似a.b.c.d等格式,忽略[] */ private static String getLinkedPath(SerialContext serialContext) { //这里有点bad smell,即要考虑parent为null,又要考虑fieldName为null,且对collection判断只能从fieldName,而不能从object入手 boolean isCollection = serialContext.fieldName instanceof Integer; boolean isFieldNameNull = serialContext.fieldName == null; if(serialContext.parent == null) return isCollection ? "" : isFieldNameNull ? "" : String.valueOf(serialContext.fieldName); String parentLinkedPath = getLinkedPath(serialContext.parent); if(isCollection || isFieldNameNull) return parentLinkedPath; return parentLinkedPath.length() == 0 ? String.valueOf(serialContext.fieldName) : parentLinkedPath + "." + serialContext.fieldName; } public static class Person { private int id; private int id2; private List<Person> children = new ArrayList<Person>(); public int getId2() { return id2; } public void setId2(int id2) { this.id2 = id2; } public int getId() { return id; } public void setId(int id) { this.id = id; } public List<Person> getChildren() { return children; } public void setChildren(List<Person> children) { this.children = children; } } public static class Person2 { private int id; private Map<String, String> infoMap; public int getId() { return id; } public void setId(int id) { this.id = id; } public Map<String, String> getInfoMap() { return infoMap; } public void setInfoMap(Map<String, String> infoMap) { this.infoMap = infoMap; } } }