java处理json与对象的转化 递归
整个类是一个case,总结了我在使用java处理json的时候遇到的问题,还有级联关系的对象如何遍历,json和对象之间的转换!
对于对象json转换中遇到的问题我参考了一篇博客,http://blog.csdn.net/xq328220454/article/details/39256589
很有益处,我在文章的后半部分照搬了过来!
首先准备数据,准备了一堆具有主子关系的对象,包含普通属性id,父对象parent,子集合list<HeadCell>,还有关联对象message;
1 @Before 2 public void setUp() throws Exception { 3 Message message = new Message("name", 1); 4 HeadCell hc1 = new HeadCell(); 5 HeadCell hc2 = new HeadCell(); 6 HeadCell hc11 = new HeadCell(); 7 HeadCell hc12 = new HeadCell(); 8 HeadCell hc21 = new HeadCell(); 9 HeadCell hc111 = new HeadCell(); 10 HeadCell hc112 = new HeadCell(); 11 12 hc111.setId("hc111"); 13 hc111.setMessage(message); 14 15 hc112.setId("hc112"); 16 hc112.setMessage(message); 17 18 hc11.setId("hc11"); 19 hc11.setMessage(message); 20 21 hc12.setId("hc12"); 22 hc12.setMessage(message); 23 24 hc21.setId("hc21"); 25 hc21.setMessage(message); 26 27 hc1.setId("hc1"); 28 hc1.setMessage(message); 29 30 hc2.setId("hc2"); 31 hc2.setMessage(message); 32 33 List<HeadCell> hcs11 = new ArrayList<>(); 34 hcs11.add(hc111); 35 hcs11.add(hc112); 36 hc11.setChildren(hcs11); 37 hc111.setParent(hc11); 38 hc112.setParent(hc11); 39 40 List<HeadCell> hcs1 = new ArrayList<>(); 41 hcs1.add(hc11); 42 hcs1.add(hc12); 43 hc1.setChildren(hcs1); 44 hc11.setParent(hc1); 45 hc12.setParent(hc1); 46 47 List<HeadCell> hcs2 = new ArrayList<>(); 48 hcs2.add(hc21); 49 hc2.setChildren(hcs2); 50 51 headCells.add(hc1); 52 headCells.add(hc2); 53 }
1 public class Message { 2 private String name; 3 private Integer age; 4 5 public Message() {} 6 7 public Message(String name, Integer age) { 8 this.name = name; 9 this.age = age; 10 } 11 12 public String getName() { 13 return name; 14 } 15 16 public void setName(String name) { 17 this.name = name; 18 } 19 20 public Integer getAge() { 21 return age; 22 } 23 24 public void setAge(Integer age) { 25 this.age = age; 26 } 27 28 }
通过递归以目录格式解析层级关系,把准备的list以树形的方式打印处理
1 @Test 2 public void chart() { 3 String str = ""; 4 buildChart(headCells, str); 5 } 6 7 private void buildChart(List<HeadCell> headCells, String str) { 8 str += "++"; 9 for (int i = 0; i < headCells.size(); i++) { 10 HeadCell headCell = headCells.get(i); 11 if (headCell.getChildren() != null && headCell.getChildren().size() > 0) { 12 System.out.println(str + headCell.getId()); 13 buildChart(headCell.getChildren(), str); 14 } else { 15 System.out.println(str + headCell.getId()); 16 } 17 } 18 }
打印结果为:
++hc1 ++++hc11 ++++++hc111 ++++++hc112 ++++hc12 ++hc2 ++++hc21
处理List<HeadCell>转化为jsonarray,当然对象是转换为jsonObject,还有一种是继承了ArrayList的对象,我有遇到过这种情况,忘了是怎么处理的了
这里转换的时候使用了config.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);是因为parent自关联会无限递归下去,所以这解析出json的值
parent为空
1 @Test 2 public void proHeadCell2Json() { 3 JsonConfig config = new JsonConfig(); 4 // config.setExcludes(new String[]{}); 5 config.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT); 6 try { 7 String array = JSONArray.fromObject(headCells, config).toString(); 8 System.out.println(array); 9 } catch (Exception e) { 10 e.printStackTrace(); 11 } 12 }
list对象转成json结果为
1 [ { 2 "children" : [ { 3 "children" : [ { 4 "children" : [], 5 "id" : "hc111", 6 "message" : { 7 "age" : 1, 8 "name" : "name" 9 }, 10 "parent" : null 11 }, { 12 "children" : [], 13 "id" : "hc112", 14 "message" : { 15 "age" : 1, 16 "name" : "name" 17 }, 18 "parent" : null 19 } ], 20 "id" : "hc11", 21 "message" : { 22 "age" : 1, 23 "name" : "name" 24 }, 25 "parent" : null 26 }, { 27 "children" : [], 28 "id" : "hc12", 29 "message" : { 30 "age" : 1, 31 "name" : "name" 32 }, 33 "parent" : null 34 } ], 35 "id" : "hc1", 36 "message" : { 37 "age" : 1, 38 "name" : "name" 39 }, 40 "parent" : null 41 }, { 42 "children" : [ { 43 "children" : [], 44 "id" : "hc21", 45 "message" : { 46 "age" : 1, 47 "name" : "name" 48 }, 49 "parent" : null 50 } ], 51 "id" : "hc2", 52 "message" : { 53 "age" : 1, 54 "name" : "name" 55 }, 56 "parent" : null 57 } ]
把json转为list对象,这里主要是级联列并不能转为级联关系的对象,会直接报错,所以我们需要递归json把每一级都转为一个对象,并且在转换时把children添加
为例外,这里要知道我们的parent是空的,message并不存在级联列,所以可以直接存在对象里面。那么我们需要建立他们的父关系和子关系,还是要递归处理!
1 @Test 2 public void proJson2HeadCell() { 3 JSONArray array = perpareHeadCell2Json(); 4 List<HeadCell> headCells = new ArrayList<>(); 5 for (int i = 0; i < array.size(); i++) { 6 JSONObject object = array.getJSONObject(i); 7 headCells.add(buildTierObj(object)); 8 } 9 } 10 11 private HeadCell buildTierObj(JSONObject object) { 12 HeadCell hc = new HeadCell(); 13 if (!StringUtils.equals("[]", object.getString("children"))) { 14 hc = (HeadCell) JSONObject.toBean(object, HeadCell.class); 15 hc.setChildren(new ArrayList<HeadCell>()); 16 hc.setParent(null); 17 JSONArray array = object.getJSONArray("children"); 18 for (int i = 0; i < array.size(); i++) { 19 HeadCell subHeadCell = buildTierObj(array.getJSONObject(i)); 20 subHeadCell.setParent(hc); 21 hc.getChildren().add(subHeadCell); 22 } 23 } else { 24 hc = (HeadCell) JSONObject.toBean(object, HeadCell.class); 25 hc.setParent(null); 26 } 27 return hc; 28 } 29 30 public JSONArray perpareHeadCell2Json() { 31 JsonConfig config = new JsonConfig(); 32 config.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT); 33 try { 34 JSONArray array = JSONArray.fromObject(headCells, config); 35 return array; 36 } catch (Exception e) { 37 e.printStackTrace(); 38 } 39 return null; 40 }
下面是json转为对象中遇到的问题的总结:
在JSON-LIB中,要转换的对象包含自身对象时,会抛出异常There is a cycle in the hierarchy,解决办法,如下,这样不会保存自关联属性
1 JsonConfig config = new JsonConfig(); 2 config.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);
自定义要被转换的字段
1 JsonConfig config = new JsonConfig(); 2 config.setJsonPropertyFilter(new PropertyFilter() { 3 @Override 4 public boolean apply(Object arg0, String arg1, Object arg2) { 5 if (arg1.equals("id") || arg1.equals("serialNumber") || arg1.equals("productName")) { 6 return false; 7 } else { 8 return true; 9 } 10 } 11 });
解决延迟加载产生异常的问题(net.sf.json.JSONException:java.lang.reflect.InvocationTargetException)
1 JsonConfig config = new JsonConfig(); 2 // 解决延迟加载产生异常的问题 3 config.setExcludes(new String[] { "handler", "hibernateLazyInitializer" });
解决数据库查询结果中,Date转换的问题(net.sf.json.JSONException:java.lang.reflect.InvocationTargetException)
1 JsonConfig config = new JsonConfig(); 2 config.registerJsonValueProcessor(java.util.Date.class, new JsonValueProcessor() { 3 @Override 4 public Object processArrayValue(Object obj, JsonConfig jsonconfig) { 5 return null; 6 } 7 8 @Override 9 public Object processObjectValue(String key, Object value, JsonConfig jsonConfig) { 10 if (value == null) 11 return ""; 12 // 注意:在判断几个父子级类型时要先判断子类型再判断父类型 13 if (value instanceof java.sql.Date) { 14 String str = DateFormat.getDateInstance(DateFormat.DEFAULT).format(value); 15 return str; 16 } else if (value instanceof java.sql.Timestamp || value instanceof java.util.Date) { 17 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); 18 String str = format.format(value); 19 return str; 20 } 21 return value.toString(); 22 } 23 });
有些字段的类型是枚举类型,可以在转换的时候将值设置为枚举类的value或者是label;
首先创建一个枚举类,这里我觉得我该写一篇关于枚举的博客,虽说不咋用。。。。。。
1 public enum Gender { 2 // 通过括号赋值,而且必须带有一个参构造器和一个属性跟方法,否则编译出错 3 // 赋值必须都赋值或都不赋值,不能一部分赋值一部分不赋值;如果不赋值则不能写构造器,赋值编译也出错 4 MAN("MAN"), WOMEN("WOMEN"); 5 6 private final String value; 7 8 // 构造器默认也只能是private, 从而保证构造函数只能在内部使用 9 Gender(String value) { 10 this.value = value; 11 } 12 13 public String getValue() { 14 return value; 15 } 16 }
配置config
1 JsonConfig config = new JsonConfig(); 2 config.registerJsonValueProcessor(Gender.class, new JsonValueProcessor() { 3 @Override 4 public Object processObjectValue(String key, Object value, JsonConfig jsonConfig) { 5 if (value instanceof Gender) { 6 Gender tmpValue = (Gender) value; 7 return tmpValue.getValue(); 8 } 9 return value.toString(); 10 } 11 12 @Override 13 public Object processArrayValue(Object arg0, JsonConfig arg1) { 14 // TODO Auto-generated method stub 15 return null; 16 } 17 });
在处理json的时候可能有提供一些封装好的API,但是掌握基础是很重要的。。。。。。。