【Java】JSON踩坑01 -- 字串多出前後雙引號和轉義符
阿新 • • 發佈:2022-01-18
場景:
呼叫後臺介面後返回這麼一串資料,不知道是在哪裡又作了一次轉義,現在得到的字串格式是:
"\"{\\\"A\\\":\\\"a\\\",\\\"B\\\":\\\"b\\\"}\""
也就是說,前後多了兩個雙引號,中間的轉義字元也被轉義了。
用System.out.println()打印出來就是
"{\"A\":\"a\",\"B\":\"b\"}"
關於JSON反序列化的坑(JAVA)
RestTemplate的getForObject()
public void test() { // 使用方法一,不帶引數 String url = "https:/://xxx/xx/x?id=666106231640"; Data data = restTemplate.getForObject(url, InnerRes.class); System.out.println(data); // 使用方法二,map傳參 url = "https://://xxx/xx/x?id={id}"; Map<String, Object> params = new HashMap<>(); params.put("id", 123); Data = restTemplate.getForObject(url, Data.class, params); System.out.println(data);
這個方法在大多數情況下都沒問題,還有postForObject()等好用的方法可以用
但是如果返回的值很奇怪,不是嚴格的JSON,那會報錯了,比如遇到一個返回的JSON,內部巢狀的內容有的在大括號外還多了雙引號,有的沒有,比如:
{ "result":"{"name":"mike","addr":"beijing"}", "code":"200", "error":"" }
也不懂對面介面為什麼要這麼做,也可能是本人見得比較少,不過也沒辦法了,只能當字串來處理了
先使用
String str = restTemplate.getForObject(url, String.class);
然後處理字串,先替換掉轉義的""和大括號兩邊的雙引號,假設取到下面這串str
str= "{\"result\":\"{\"name\":\"mike\",\"addr\":\"beijing\"}\",\"code\":\"200\",\"error\":\"\"}"; str = str.replace("\\",""); str = str.replace("\"{","{"); str = str.replace("}\"","}");
然後使用ObjectMapper的readValue()轉化為物件
// 建立ObjectMapper ObjectMapper mapper = new ObjectMapper(); // 下面這步的作用就是忽略json中存在,但java中的目標類中不存在的欄位,否則會反序列化報錯 mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); MyObj obj = mapper.readValue(str,MyObj);
如果MyObj巢狀多個內部類的話,不能夠越級訪問,如:
@Getter @Setter @ToString @AllArgsConstructor @NoArgsConstructor public static class test{ private String one; private String two; private Mytest mytest; @Getter @Setter @ToString @AllArgsConstructor @NoArgsConstructor public static class Mytest{ private String mytest1; private String mytest2; } }
JSON中存在
{ "one": "valone", "two": "valtwo", "mytest": { "mytest1": "t1", "mytest2": "t2" } }
想要獲取mytest1的內容,就要建立一個Mytest的內部類,然後才會匹配
最好要把裡面各個欄位都設為public static,如果是private的話,mapper.readValue()返回的對應欄位是null,具體原因未知…
猜想,可能是與ObjectMapper的反射機制有關,private就訪問不到了,但是後來發現我有一個三層的內部類,外面兩層用private的欄位是可以獲取到的,第三層後就是null了,
必須改成public才能獲取到
我使用了lombok,不知道會不會於此有關,希望有知道原因的大佬希望能指點