如何用Jackson解析含有转义字符的JSON到Java对象?

栏目: 后端 · 前端 · 发布时间: 7年前

内容简介:转载请注明出处:如果一个JSON字符串里有一个字段,它的值又是一个完整的JSON字符串,那么这时候,它可能会含有转义字符。举个例子,我们有一个文件  codelast.json,它的内容为:现在要用Jackson解析它为一个Java对象,怎么做?

转载请注明出处: https://www.codelast.com/

如果一个JSON字符串里有一个字段,它的值又是一个完整的JSON字符串,那么这时候,它可能会含有转义字符。举个例子,我们有一个文件  codelast.json,它的内容为:

 {"aaa":"{\"ccc\":\"ccc\",\"ddd\":\"ddd\"}","bbb":{"ccc":"ccc","ddd":"ddd"}}

现在要用Jackson解析它为一个 Java 对象,怎么做?

我们先把这个JSON格式化,便于观察它的结构:

{
    "aaa": "{\"ccc\":\"ccc\",\"ddd\":\"ddd\"}", 
    "bbb": {
        "ccc": "ccc", 
        "ddd": "ddd"
    }
}

所以按照Jackson的套路,我们似乎很容易就可以写出对应的JSON解析代码,先定义几个POJO:

A.java 的主要代码:

public class A {
  private AAA aaa;
  private BBB bbb;

  public AAA getAaa() {
    return aaa;
  }

  public void setAaa(AAA aaa) {
    this.aaa = aaa;
  }

  public BBB getBbb() {
    return bbb;
  }

  public void setBbb(BBB bbb) {
    this.bbb = bbb;
  }
}

文章来源: https://www.codelast.com/

AAA.java 的主要代码:

public class AAA {
  private String ccc;
  private String ddd;

  public String getCcc() {
    return ccc;
  }

  public void setCcc(String ccc) {
    this.ccc = ccc;
  }

  public String getDdd() {
    return ddd;
  }

  public void setDdd(String ddd) {
    this.ddd = ddd;
  }
}

文章来源: https://www.codelast.com/

BBB.java 的主要代码:

public class BBB {
  private String ccc;
  private String ddd;

  public String getCcc() {
    return ccc;
  }

  public void setCcc(String ccc) {
    this.ccc = ccc;
  }

  public String getDdd() {
    return ddd;
  }

  public void setDdd(String ddd) {
    this.ddd = ddd;
  }
}

文章来源: https://www.codelast.com/

然后就是解析的逻辑:

String json = FileUtils.readFileToString(new File("/home/codelast/codelast.json"));
ObjectMapper mapper = new ObjectMapper();
A data = mapper.readValue(json, A.class);

我们的目的是把codelast.json这个文件里保存的JSON字符串解析成类A的一个对象data。

这不是很简单嘛?要不运行一下试试看?

马上报错:

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.codelast.AAA` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('{"ccc":"ccc","ddd":"ddd"}')

at [Source: (String)"{"aaa":"{\"ccc\":\"ccc\",\"ddd\":\"ddd\"}","bbb":{"ccc":"ccc","ddd":"ddd"}}

"; line: 1, column: 8] (through reference chain: com.codelast.A["aaa"])

at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)

at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1342)

at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1031)

at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:371)

at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:323)

at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1366)

at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:171)

at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:161)

at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127)

at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)

at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)

at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)

at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2992)

文章来源: https://www.codelast.com/

这是什么情况?事实上,这就是由于JSON的“aaa”这个字段里面包含转义字符造成的,如果你Google一下,可能会找到 这个 知乎帖子,它告诉我们,要为Jackson的 ObjectMapper 设置一个属性为true: Feature.ALLOW_UNQUOTED_CONTROL_CHARS

所以我们可以试试:

String json = FileUtils.readFileToString(new File("/home/codelast/codelast.json"));
ObjectMapper mapper = new ObjectMapper();
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
A data = mapper.readValue(json, A.class);

再执行代码,会发现报一样的错。

所以上面的解决方案是 无效 的。

文章来源: https://www.codelast.com/

正确解决这个问题的姿势,是参考 Stack Overflow的 这个 帖子。里面说到,应该创建一个 JsonDeserializer 来搞定这个问题。下面,我就把正确的代码依次贴上来:

A.java 的主要代码(和之前不一样,这里使用了一个自定义的

AAADeserializer

):

public class A {
  @JsonDeserialize(using = AAADeserializer.class)
  private AAA aaa;

  private BBB bbb;

  public AAA getAaa() {
    return aaa;
  }

  public void setAaa(AAA aaa) {
    this.aaa = aaa;
  }

  public BBB getBbb() {
    return bbb;
  }

  public void setBbb(BBB bbb) {
    this.bbb = bbb;
  }
}

文章来源: https://www.codelast.com/

AAA.java 的主要代码(和之前一样没变化):

public class AAA {
  private String ccc;
  private String ddd;

  public String getCcc() {
    return ccc;
  }

  public void setCcc(String ccc) {
    this.ccc = ccc;
  }

  public String getDdd() {
    return ddd;
  }

  public void setDdd(String ddd) {
    this.ddd = ddd;
  }
}

文章来源: https://www.codelast.com/

BBB.java的主要代码(和之前一样没变化):

public class BBB {
  private String ccc;
  private String ddd;

  public String getCcc() {
    return ccc;
  }

  public void setCcc(String ccc) {
    this.ccc = ccc;
  }

  public String getDdd() {
    return ddd;
  }

  public void setDdd(String ddd) {
    this.ddd = ddd;
  }
}

文章来源: https://www.codelast.com/

下面就是关键的 AAADeserializer.java 的主要代码:

public class AAADeserializer extends JsonDeserializer<AAA> {
  private static final ObjectMapper mapper = new ObjectMapper();

  @Override
  public AAA deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
    return mapper.readValue(jsonParser.getText(), AAA.class);
  }
}

文章来源: https://www.codelast.com/

然后就可以解析JSON了:

String json = FileUtils.readFileToString(new File("/home/codelast/codelast.json"));
ObjectMapper mapper = new ObjectMapper();
A data = mapper.readValue(json, A.class);

你这时候再运行一下这段代码,就会发现不再报错,JSON已经成功解析到对象 data 中,问题解决!

[原创] 如何用Jackson解析含有转义字符的字符串到Java对象?


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Java并发编程的艺术

Java并发编程的艺术

方腾飞、魏鹏、程晓明 / 机械工业出版社 / 2015-7-1 / 59.00元

并发编程领域的扛鼎之作,作者是阿里和1号店的资深Java技术专家,对并发编程有非常深入的研究,《Java并发编程的艺术》是他们多年一线开发经验的结晶。本书的部分内容在出版早期发表在Java并发编程网和InfoQ等技术社区,得到了非常高的评价。它选取了Java并发编程中最核心的技术进行讲解,从JDK源码、JVM、CPU等多角度全面剖析和讲解了Java并发编程的框架、工具、原理和方法,对Java并发编......一起来看看 《Java并发编程的艺术》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具