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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM