整個類是一個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,但是掌握基礎是很重要的。。。。。。。