jacksonによるJsonシーケンス化と逆シーケンス化

11198 ワード

概要


日常開発ではJSONをデータ転送のフォーマットとして利用することが多く,そのためにJSONシーケンス化(オブジェクトをJSON文字列に変換)や逆シーケンス化(JSON文字列を指定したデータ型に変換)によく用いられる.
本文は主にfasterxmlを利用することを紹介する.jacksonはJSONシーケンス化と逆シーケンス化を実現し,Unrecognized fieldに遭遇した問題について解決する.

Gradle依存


fasterxmlを利用する.jacksonはjackson-core,jackson-databindおよびjackson-annotationsに依存しbuild.gradleファイルに依存を追加する例は、次のとおりです.
dependencies {
        compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.5'
        compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.9.5'
        compile group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.9.5'


    }

シーケンス化と逆シーケンス化の実装


JSONツール類


JSONツールクラスを構築し、JSONシーケンス化と逆シーケンス化を実現します.主に使用されるクラスはcom.fasterxml.jackson.databind.ObjectMapperで、コードの例は以下の通りです.
package com.notepad.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by YM on 2017/6/11.
 */
public class JsonSerializer {

    /**
     * JSON   
     *
     * @param object   
     * @return JSON   
     */
    public static String serialize(Object object) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            return mapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * JSON       
     *
     * @param jsonStr JSON   
     * @return a Map
     */
    public static Map deserialize(String jsonStr) {
        try {
            return deserialize(jsonStr, Map.class);
        } catch (Exception e) {
            e.printStackTrace();
            return new HashMap();
        }
    }

    public static  T deserialize(String jsonStr, Class classType) throws Exception {
        return new ObjectMapper().readValue(jsonStr, classType);
    }
}

Entity


作成したJSONツールクラスをテストするために、Entityオブジェクトを定義します.
構築するためのEntityオブジェクトがJSONツールクラスによって操作される場合、Entityについていくつかの説明があります.
  • Entityオブジェクトには、デフォルトのコンストラクタ
  • が必要です.
  • メンバー変数には、対応するSetterメソッド
  • が必要です.
  • オプション:@JsonPropertyで対応する文字の名前をカスタマイズできます.@JsonProperty(「UID」)のように、シーケンス化時uidフィールドはUIDとして表示され、同じ逆シーケンス化時に文字列内のUIDに対応する値を見つけてuidにコピーします.
  • オプション:@JsonIgnore注記で、シーケンス化を必要としないメンバー変数をフィルタできます.例:
  • package com.notepad.thinkingnote.domain;
    
    import com.fasterxml.jackson.annotation.JsonProperty;
    
    /**
     * Description:     
     * 

    * Create: 2018/9/6 22:37 * * @author Yang Meng */

    public class Entity { public Entity() {} public Entity(String uid, String name) { this.uid = uid; this.name = name; } /** */ @JsonProperty("UID") private String uid; @JsonProperty("name") private String name; public void setUid(String uid) { this.uid = uid; } public String getUid() { return uid; } public void setName(String name) { this.name = name; } public String getName() { return name; } }

    ユニットテスト


    ユニットテストを作成し、Entityのシーケンス化と逆シーケンス化をテストします.例は次のとおりです.
    package com.notepad.thinkingnote.domain;
    
    import com.notepad.util.JsonSerializer;
    import org.junit.Test;
    
    import static org.junit.Assert.*;
    
    /**
     * Description:             
     * 

    * Create: 2018/9/6 22:41 * * @author Yang Meng */

    public class EntityTest { @Test public void testSerialize() throws Exception { Entity entity = new Entity("James", "James"); System.out.println(JsonSerializer.serialize(entity)); } @Test public void testDeserialize() throws Exception { String test = "{\"UID\":\"James\",\"name\":\"James\"}"; Entity entity = JsonSerializer.deserialize(test, Entity.class); System.out.println(entity.getUid() + ":" + entity.getName()); } }

    出力結果は次のとおりです.
    // entity      ,     UID
    {"UID":"James","name":"James"}
    
    // entity      
    James:James

    UnrecognizedPropertyException


    以上の紹介を通して、JSONのシーケンス化と逆シーケンス化を基本的に理解しましたが、時々問題に遭遇することがあります.
    このような状況を考慮して,Httpインタフェースから返されるJSON文字列に対して,具体的なEntityオブジェクトを構築したが,Httpインタフェースに突然フィールドtypeが追加され,上記の方法で構築された場合,どのような問題が発生するのか.
    単一サンプルをもう1つ作成します.
    @Test
        public void testDeserialize() throws Exception {
            String test = "{\"UID\":\"James\",\"name\":\"James\", \"type\":\"entity\"}";
            Entity entity = JsonSerializer.deserialize(test, Entity.class);
            System.out.println(entity.getUid() + ":" + entity.getName());
        }

    UnrecognizedPropertyException異常が発生しました:
    com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "type" ....

    すなわち、新しく追加したtype文字は認識できません.どうやってこの問題を解決しますか?ここでは2つの方法を提供します.

    JsonIgnoreProperties注記


    fasterxmlを利用する.jacksonが提供する@JsonIgnoreProperties注記は、認識できない属性に対してフィルタリングされます.ここでは主に、逆シーケンス化が必要なオブジェクトEntityを変更します.例を次に示します.
    //              
    @JsonIgnoreProperties(ignoreUnknown = true)
    public class Entity {...}

    DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES


    メソッド1の修正は,逆シーケンス化が必要なクラスごとに修正する必要があり,不便である.
    方法2 JSONツール類の逆シーケンス化方法を修正することにより、DeserializationFeatureを設定する.FAIL_ON_UNKNOWN_PROPERTIESの値はfalseで、1回の修正だけですべてのオブジェクトを適用できます.
    例は次のとおりです.
    public static  T deserialize(String jsonStr, Class classType) throws Exception {
            //   configure,   DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES false
            //                   
            return new ObjectMapper()
                    .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
                    .readValue(jsonStr, classType);
        }

    まとめ


    本稿では主にjacksonによるJsonシーケンス化と逆シーケンス化を紹介し,UnrecognizedPropertyException異常を解決する2つの方法を示した.