在Java中解析JSON时如何忽略未知属性– Jackson @JsonIgnoreProperties注释示例

使用Jackson API在Java中解析JSON时的常见问题之一是,当您的JSON包含未知属性(即您的Java类没有对应于所有JSON属性的所有字段)时,该操作将失败。 例如,如果您正在使用REST Web服务中的JSON,并且明天他们在JSON中添加了一个新字段,则您的代码将中断,因为Jackson将抛出UnrecognizedPropertyException并停止解析JSON。 这很麻烦,如果您不知道,可能会导致生产问题。 当开发人员交付代码以使用来自REST API的数据而未正确处理未知字段时,我遇到了这个问题。

该代码可以正常工作几个月,但是一旦源系统添加了一个新字段并添加到REST API中,它就崩溃了。 开发人员选择忽略更新,因为我们对该字段不感兴趣,但是他没有预见到它将影响JSON解析

无论如何,我们的错是我们没有正确地检查代码,并允许他在不处理未知文件的情况下将其代码发布到生产环境中。 如果他更熟悉Jackson图书馆,就可以避免这个问题。

Jackson API提供了两种忽略未知字段的方法 ,一种是在类级别使用@JsonIgnoreProperties批注,另一种是在ObjectMapper级别使用configure()方法。

您将在本文中看到这两种方法,并了解如何使用它们以及何时使用<@code> JsonIgnoreProperties以及何时在ObjectMapper级别全局忽略JSON中的未知字段。

使用@JsonIgnoreProperties忽略未知属性

如果要创建一个Model类来表示Java中的JSON,则可以使用@JsonIgnoreProperties (ignoreUnknown = true)对该类进行注释,以忽略任何未知字段。 这意味着,如果明天在JSON上添加一个代表您的模型的新字段,那么Jackson在用Java解析JSON时将不会抛出UnrecognizedPropertyException

如果只想忽略该Model类的未知属性,则可以使用此方法,但这是首选方法,因为它为您提供了更多控制权。

我们来看一个在Java中使用@JsonIgnoreProperties的示例:

假设我遵循以下JSON,它代表了我最喜欢的书《 Effective Java 3rd Edition》 ,一本必须为2018年每个Java开发人员阅读的书以及我项目中的Java模型类:

如果明天,我在JSON中添加一个名为“ edition”的新字段,则此JSON的解析将失败,并出现UnrecognizedPropertyException错误。 就像是 :

线程“ main”中的异常com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException:无法识别的字段“ edition”(电子书类),未标记为可忽略(3个已知属性:,“ title”,“ price”,“ author”) )”

这意味着Jackson无法在EBook类中找到JSON中“ edition”属性的任何字段,因此会UnrecognizedPropertyException错误。

您可以使用@JsonIgnoreProperties批注来解决此问题并防止此错误,如下所示:

@JsonIgnoreProperties(ignoreUnknown = true)
class EBook{
  private String title;
  private String author;
  private int price; 
  ..

}

我们刚刚将整个模型类注释为@JsonIgnoreProperties (ignoreUnknown = true),这意味着JSON字符串中的任何未知属性,即在EBook类中没有对应字段的任何属性都将被忽略。 如果您再次编译并运行程序,它将可以正常工作。

在Jackson 2.x中, @JsonIgnoreProperties驻留在com.fasterxml.jackson.annotation包中,因此您需要将其导入为:

导入com.fasterxml.jackson.annotation.JsonIgnoreProperties。

如果您使用的是杰克逊API的旧版本,例如杰克逊1.x,则此注释属于不同的软件包,请当心,特别是如果您的类路径中同时包含杰克逊1.x和杰克逊2.x。

使用Jackson全局忽略JSON中的未知属性

处理您正在解析的JSON中的未知属性的另一种方法是将ObjectMapper配置为在遇到未知属性时不失败。 这还将解决UnrecognizedPropertyException的问题。 您可以通过调用configure()方法来启用此设置,如下所示:

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

现在,它将忽略要解析的任何JSON的未知属性。仅当无法使用@JsonIgnoreProperties注释对类进行注释时,才应使用此选项。

顺便说一句,如果您不熟悉Java中的JSON解析库,那么从Udemy上使用Java API,jQuery和REST Web Services进行JSON是一个不错的起点。

使用Jackson解析JSON时忽略未知属性的Java程序

让我们看看到目前为止我们所学到的一切。 顺便说一句,如果您对我的String JSON和很多“ / r / n”字符串感到困惑,请不要担心。 我还没有手动完成。 我用这个
Eclipse复制我的JSON的技巧 ,它自动包含必要的转义字符。 这是必需的,因为JSON字符串用双引号(“”)引起来,需要在Java中对其进行转义。

顺便说一句,如果您不熟悉Eclipse IDE,那么我建议您查看Udemy上的“ 初学者Eclipse Java IDE培训课程 ”以学习它。 对于Java开发人员而言,重要的是要充分了解其工具,尤其是IDE,以便他们有效地开发,测试,调试和运行Java应用程序。

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;

/*
 * Java Program to iterate over JSONObject of json-simple
 */
public class JacksonTest {

  private static String json = "{\r\n" + "\"title\" : \"Effective Java\",\r\n"
      + "\"author\" : \"Joshua Bloch\",\r\n" + "\"price\" : 37,\r\n"
      + "\"edition\" : 37\r\n" + "}";

  public static void main(String args[]) throws IOException {

    // let's parse JSON with a date field
    ObjectMapper mapper = new ObjectMapper();
    // mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
    // false);

    EBook effectiveJava = mapper.readValue(json, EBook.class);
    System.out.println("Input json string");
    System.out.println(json);
    System.out.println("Generated java class: ");
    System.out.println(effectiveJava);

  }

}

class EBook {
  private String title;
  private String author;
  private int price;

  public EBook() {
    // no argument constructor required by Jackson
  }

  public EBook(String title, String author, int price) {
    this.title = title;
    this.author = author;
    this.price = price;
  }

  public String getTitle() {
    return title;
  }

  public String getAuthor() {
    return author;
  }

  public int getPrice() {
    return price;
  }

  public void setTitle(String title) {
    this.title = title;
  }

  public void setAuthor(String author) {
    this.author = author;
  }

  public void setPrice(int price) {
    this.price = price;
  }

  @Override
  public String toString() {
    return "EBook [title=" + title + ", author=" + author + ", price=" + price
        + "]";
  }

}

Output:
Input json string
{
"title" : "Effective Java",
"author" : "Joshua Bloch",
"price" : 37,
"version" : 37
}
Generated java class: 
EBook [title=Effective Java, author=Joshua Bloch, price=37]

我有一个名为EBook的模型类,该类用@JsonIgnoreProperties (ignoreUnknown = true)注释,以忽略未知属性。

如果仔细观察,我们的JSON字符串包含Java类中未定义的“ edition”属性,但该程序可以运行,因为我们已使用@JsonIgnoreProperties (ignoreUnknown = true)标记了EBook。

如果要测试此程序,则只需删除该批注并运行该程序,它将引发以下错误。

Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field
 "edition" (class EBook), not marked as ignorable (3 known properties: , "title", "price", "author"])
at [Source: java.io.StringReader@19dfb72a; line: 5, column: 14] (through reference chain: EBook["edition"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:79)
at com.fasterxml.jackson.databind.DeserializationContext.reportUnknownProperty(DeserializationContext.java:555)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:708)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1160)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:315)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2888)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2034)
at JacksonTest.main(JacksonTest.java:30)

发生这种情况是因为“版本”字段仅出现在JSON中,而没有出现在Java类中。 如果您放回注解,则代码将再次起作用。

您可以类似地在对象映射器级别测试如何忽略未知字段 ,而不用@JsonIgnoreProperties批注,而只需取消注释
代码中的mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false)行并运行程序。 这一次它也将起作用,因为杰克逊忽略了所有未知属性。

这就是在使用Jackson API在Java中解析JSON时如何忽略未知属性的全部内容。 您可以通过使用@JsonIgnoreProperties批注或通过禁用FAIL_ON_UNKNOWN_PROPERTIES来配置反序列化过程中遇到未知属性时ObjectMapper不会失败而做到这一点。

但是,首选方法是使用@JsonIgnoreProperties (ignoreUnknown = true)在类级别忽略未知属性,并且仅当无法使用此注释来注释类(即您不拥有该类)时才在ObjectMapper级别执行此操作。 最好的做法是使用@JsonIgnoreProperties注释模型类,以避免我在第一段中解释的问题。

您可能喜欢的其他Java和JSON资源

运行中的JSON:构建基于JSON的应用程序
如何使用Gson解析JSON?
Java开发人员应该知道的5个JSON解析库 如何在Java中解析JSON数组? 如何在Java中将JSON转换为HashMap? Java开发人员在2018年应该学习的10件事 带有Java API,jQuery和REST Web服务的JSON

感谢您到目前为止阅读本文。 如果您喜欢这篇文章,请与您的朋友和同事分享。 如果您有任何疑问或疑问,请留下笔记。

翻译自: https://www.javacodegeeks.com/2018/01/ignore-unknown-properties-parsing-json-java-jackson-jsonignoreproperties-annotation-example.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然,我可以为您提供一个Java使用Jackson实现多态解析JSON示例。这里是一个基本的示例代码: ``` public class Animal { public String name; public String type; } @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type" ) @JsonSubTypes({ @JsonSubTypes.Type(value = Dog.class, name = "dog"), @JsonSubTypes.Type(value = Cat.class, name = "cat"), }) public abstract class AnimalMixin { @JsonCreator public AnimalMixin(@JsonProperty("name") String name) { } } public class Dog extends Animal { public String breed; public Dog() {} public Dog(String name, String breed) { this.name = name; this.breed = breed; this.type = "dog"; } } public class Cat extends Animal { public int age; public Cat() {} public Cat(String name, int age) { this.name = name; this.age = age; this.type = "cat"; } } public static void main(String[] args) throws JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); String json = "{ \"name\": \"Fido\", \"type\": \"dog\", \"breed\": \"beagle\" }"; Animal animal = mapper.readValue(json, Animal.class); System.out.println(animal.name); System.out.println(((Dog)animal).breed); } ``` 在这个示例,我们有一个Animal类,它有一个name属性和一个type属性。type属性用于标识动物的类型,它将在JSON解析期间用于决定将JSON转换为哪个子类。我们通过@JsonTypeInfo注释和@JsonSubTypes注释来指示Jackson使用多态解析JSON。@JsonTypeInfo注释告诉Jackson使用"type"属性来确定JSON应该被反序列化为哪个类。@JsonSubTypes注释告诉Jackson哪些子类需要被考虑。 我们还有一个AnimalMixin抽象类,它用于处理将JSON转换为适当的子类。在这个例子,我们有两个实现:Dog和Cat。两个类都有它们自己的属性,但都继承自Animal类。 在main方法,我们首先创建一个ObjectMapper对象,然后使用readValue方法将JSON字符串转换为Animal对象。然后我们打印了Animal对象的name属性和子类特有的属性。 这是一个Java使用Jackson实现多态解析JSON的基本示例。我希望它能帮助您。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值