1. 程式人生 > 其它 >【Java】JSON踩坑01 -- 字串多出前後雙引號和轉義符

【Java】JSON踩坑01 -- 字串多出前後雙引號和轉義符

場景:

  呼叫後臺介面後返回這麼一串資料,不知道是在哪裡又作了一次轉義,現在得到的字串格式是:

"\"{\\\"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,不知道會不會於此有關,希望有知道原因的大佬希望能指點