Java
 Computer >> コンピューター >  >> プログラミング >> Java

JavaでJSONの逆シリアル化時に発生するエラーを処理する方法

JSONをJavaオブジェクトに逆シリアル化(デシリアライズ)する際、未知のプロパティが含まれているとエラーが発生することがあります。Jacksonでは、DeserializationProblemHandlerクラスを登録することで、逆シリアル化の過程で回復可能な問題が検出されたときに独自の処理を実行できます。

具体的には、DeserializationProblemHandlerクラスのhandleUnknownProperty()メソッドをオーバーライドして実装することで、JSONの逆シリアル化中に発生したエラーを柔軟にハンドリングできます。

構文

public boolean handleUnknownProperty(DeserializationContext ctxt, JsonParser p, JsonDeserializer deserializer, Object beanOrClass, String propertyName) throws IOException

このメソッドがtrueを返すと、「エラーは処理済みである」と判断され、逆シリアル化は続行されます。一方、falseを返すと、その時点で逆シリアル化が即座に中断されます。

実装例

import java.io.*;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.*;

public class DeserializationErrorTest {
    public static void main(String[] args) throws JsonMappingException, JsonGenerationException, IOException {
        String jsonString = "{\"id\":\"101\", \"name\":\"Ravi Chandra\", \"address\":\"Pune\", \"salary\":\"40000\" }";
        ObjectMapper objectMapper = new ObjectMapper();
        DeserializationProblemHandler deserializationProblemHandler = new UnMarshallingErrorHandler();
        objectMapper.addHandler(deserializationProblemHandler);
        Customer customer = objectMapper.readValue(jsonString, Customer.class);
        System.out.println(customer);
    }
}

// 独自のエラーハンドラークラス
class UnMarshallingErrorHandler extends DeserializationProblemHandler {
    @Override
    public boolean handleUnknownProperty(DeserializationContext ctxt, JsonParser jp, JsonDeserializer deserializer, Object beanOrClass, String propertyName) throws IOException, JsonProcessingException {
        boolean result = false;
        super.handleUnknownProperty(ctxt, jp, deserializer, beanOrClass, propertyName);
        System.out.println("Property with name '" + propertyName + "' doesn't exist in Class of type '" + beanOrClass.getClass().getName() + "'");
        // trueを返すとエラーを処理済みとみなし、逆シリアル化を続行。
        // falseを返すと、その場で逆シリアル化を即座に停止。
        return true;
    }
}

// Customerクラス
class Customer {
    private int id;
    private String name;
    private String address;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    @Override
    public String toString() {
        return "Customer [id=" + id + ", name=" + name + ", address=" + address + "]";
    }
}

この例では、JSONデータにsalaryというフィールドが含まれていますが、Customerクラスには該当するフィールドが存在しません。ここでカスタムハンドラーがどのように動作するかを見てみましょう。

trueを返した場合の出力

Property with name 'salary' doesn't exist in Class of type 'Customer'
Customer [id=101, name=Ravi Chandra, address=Pune]

trueを返した場合は、未知のプロパティ「salary」に関する警告メッセージが出力された後も処理が継続され、最終的にCustomerオブジェクトが正常に生成されます。

falseを返した場合の出力

Property with name 'salary' doesn't exist in Class of type 'Customer'
Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "salary" (class Customer), not marked as ignorable (3 known properties: "id", "address", "name"])
at [Source: (String)"{"id":"101", "name":"Ravi Chandra", "address":"Pune", "salary":"40000" }"; line: 1, column: 65] (through reference chain: Customer["salary"]) at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:61)
at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:840)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1179)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1592) at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1570) at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:294)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4202)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3205)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3173)
at DeserializationErrorTest.main(DeserializationErrorTest.java:12)

falseを返した場合は、警告メッセージの後にUnrecognizedPropertyExceptionがスローされ、逆シリアル化が中断されます。このように、戻り値を制御することで、未知のプロパティを無視して処理を続けるか、厳密にエラーとして扱うかを選択できます。


  1. JavaでJacksonのObject Modelを使ってJSONデータをマッピングする方法

    JavaでJSONを扱う際に広く利用されているJacksonライブラリでは、ObjectMapperクラスがJavaオブジェクトとJSON構造の間の相互変換を担います。 JSONデータをオブジェクトモデル(Object Model)として表現し、特定のJavaオブジェクトへマッピングするには、ツリー構造を活用します。このアプローチでは、JSONコンテンツ全体が一度にメモリへ読み込まれ、木構造として保持されます。 処理の流れはシンプルです。まずJSONデータをJsonNodeオブジェクトとして読み込み、続いてObjectMapperクラスのtreeToValue()メソッドを呼び出すことで、その

  2. JavaでJsonPointerインターフェースを使用してJSONのキーの値を取得する方法

    JSONPointerは、JSONドキュメント内の特定のキーの値へアクセスするための文字列構文を定義した標準規格です。Jsonクラスの静的ファクトリメソッドであるcreatePointer()を呼び出すことで、JSONPointerのインスタンスを生成できます。JSONPointerでは、すべての文字列構文がスラッシュ「/」で始まるのが特徴です。キーの値を取得するには、JSONPointerオブジェクトに対してgetValue()メソッドを呼び出します。 前提条件 この記事のコードを実行するには、Java EE / Jakarta EEに含まれるJSON Processing(JSON-P)の