content: package com.alibaba.json.bvt.serializer;
  
  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);
  			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.getFieldName() instanceof Integer;
  		boolean isFieldNameNull = serialContext.getFieldName() == null;
  		if(serialContext.getParent() == null)
  			return isCollection ? "" : isFieldNameNull ? "" : String.valueOf(serialContext.getFieldName());
  		String parentLinkedPath = getLinkedPath(serialContext.getParent());
  		if(isCollection || isFieldNameNull)
  			return parentLinkedPath;
  		return
  			parentLinkedPath.length() == 0 ? String.valueOf(serialContext.getFieldName()) :
  				parentLinkedPath + "." + serialContext.getFieldName();
  	}
  
  	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;
  		}
  	}
  }
  