【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}"; Mapparams = 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,不知道会不会于此有关,希望有知道原因的大佬希望能指点