Jackson ObjectMapperの使用


テキストアドレス
1.概要
JacksonのObjectMapperクラスを使用してJavaオブジェクトをJsonにシーケンス化し、JsonをJavaオブジェクトに逆シーケンス化する方法について説明します.
2.Maven依存
        <dependency>
            <groupId>com.fasterxml.jackson.coregroupId>
            <artifactId>jackson-databindartifactId>
            <version>2.10.1version>
        dependency>

この依存は、クラスパスに次のライブラリを転送可能に追加します.
  • jackson-annotations-2.10.1.jar
  • jackson-core-2.10.1.jar
  • jackson-databind-2.10.1.jar

  • 3.ObjectMapperによるシーケンス化と逆シーケンス化
    基本的な読み書き操作から始めましょう.
  • ObjectMapperのreadValueを使用してJSONコンテンツをJavaオブジェクトに解析または逆シーケンス化できます.
  • writeValueを使用して、JavaオブジェクトをJSON出力にシーケンス化できます.本明細書では、2つのフィールドを有する次のCarクラスをオブジェクトとしてシーケンス化または逆シーケンス化する:
  • public class Car {
     
        private String color;
        private String type;
     
        // getters/setters
    }
    

    3.1. Javaオブジェクト転JSON
    ObjectMapperクラスのwriteValueメソッドを使用してJavaオブジェクトをJSONにシーケンス化する例を見てみましょう.
    ObjectMapper objectMapper = new ObjectMapper();
    Car car = new Car("yellow", "renault");
    objectMapper.writeValue(new File("target/car.json"), car);
    

    ファイルの内容は次のとおりです.
    {"color":"yellow","type":"renault"}
    

    ObjectMapperクラスのwriteValueAsStringメソッドとwriteValueAsBytesメソッドはJavaオブジェクトからJSONを生成し、生成したJSONを文字列またはバイト配列として返します.
    String carAsString = objectMapper.writeValueAsString(car);
    

    3.2. JSONからJson対象へ
    以下に、ObjectMapperクラスを使用してJSON文字列をJavaオブジェクトに変換する簡単な例を示します.
    ObjectMapper objectMapper = new ObjectMapper();
    String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";
    Car car = objectMapper.readValue(json, Car.class); 
    

    readValue()関数は、JSON文字列を含むファイルなど、他の形式の入力も受け入れます.
    Car car = objectMapper.readValue(new File("src/test/resources/json_car.json"), Car.class);
    

    またはURL
    Car car = objectMapper.readValue(new URL("file:src/test/resources/json_car.json"), Car.class);
    

    3.3. JSON回転ジャックソンJsonNode
    また、JSONをJsonNodeオブジェクトとして解析し、特定のノードからデータを取得するために使用できます.
    String json = "{ \"color\" : \"Black\", \"type\" : \"FIAT\" }";
    JsonNode jsonNode = objectMapper.readTree(json);
    String color = jsonNode.get("color").asText();
    // Black
    

    3.4. JsonからJava Listへ
    TypeReferenceを使用して、配列形式のJSONをJavaオブジェクトリストに解析できます.
    String jsonCarArray = "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]";
    List<Car> listCar = objectMapper.readValue(jsonCarArray, new TypeReference<List<Car>>(){});
    

    3.5. JsonからJava Mapへ
    同様に、JSONをJava Mapとして解析することができます.
    String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";
    Map<String, Object> map = objectMapper.readValue(json, new TypeReference<Map<String,Object>>(){});
    

    4.高度な機能
    Jacksonライブラリの最大の利点の1つは、高度にカスタマイズ可能なシーケンス化と逆シーケンス化プロセスです.このセクションでは、JSONデータの入力または出力が、データを生成または使用するオブジェクトと異なる場合がある高度な機能について説明します.
    4.1. シーケンス化と逆シーケンス化の構成
    JSONオブジェクトをJavaクラスに変換する場合、JSON文字列にいくつかの新しいフィールドがある場合、デフォルトのプロシージャでは、Carにyear属性がないなどの例外が発生します.
    String jsonString = "{ \"color\" : \"Black\", \"type\" : \"Fiat\", \"year\" : \"1970\" }";
    

    上記の例のデフォルト解析では、ClassCarのJavaオブジェクトに対するJSON文字列によってUnrecognizedPropertyExceptionが例外となります.configureメソッドでは、新しいフィールドを無視するためにデフォルトのプロシージャを拡張できます.
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    Car car = objectMapper.readValue(jsonString, Car.class);
     
    JsonNode jsonNodeRoot = objectMapper.readTree(jsonString);
    JsonNode jsonNodeYear = jsonNodeRoot.get("year");
    String year = jsonNodeYear.asText();
    
  • もう1つのオプションはFAIL_ON_NULL_FOR_PRIMITIVESで、クラスの属性がNULLであることを許可するかどうかを定義します:
  • objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false);
    
  • 同様に、FAIL_ON_NUMBERS_FOR_ENUMは、列挙値を数値にシーケンス化/逆シーケンス化することを許可するかどうかを制御する:
  • .
    objectMapper.configure(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS, false);
    

    公式サイトでは、シーケンス化と逆シーケンス化機能の完全なリストを見つけることができます.
    4.2. カスタムシーケンス化と逆シーケンス化
    ObjectMapperクラスのもう一つの基本機能は、カスタムシーケンサと逆シーケンサを登録できることです.JSONを入力または出力する構造が、シーケンス化または逆シーケンス化する必要があるJavaクラスと異なる場合に便利です.
    カスタムJSONシーケンサの例を次に示します.
    public class CustomCarSerializer extends StdSerializer<Car> {
         
        public CustomCarSerializer() {
            this(null);
        }
     
        public CustomCarSerializer(Class<Car> t) {
            super(t);
        }
     
        @Override
        public void serialize(
          Car car, JsonGenerator jsonGenerator, SerializerProvider serializer) {
            jsonGenerator.writeStartObject();
            jsonGenerator.writeStringField("car_brand", car.getType());
            jsonGenerator.writeEndObject();
        }
    }
    

    このカスタムシーケンサは、次のように呼び出すことができます.
            ObjectMapper mapper = new ObjectMapper();
            
            SimpleModule module = new SimpleModule("CustomCarSerializer", new Version(1, 0, 0, null, null, null));
            module.addSerializer(Car.class, new CustomCarSerializer());
            mapper.registerModule(module);
            
            Car car = new Car("yellow", "renault");
            String carJson = mapper.writeValueAsString(car);
            System.out.println(carJson); // {"car_brand":"renault"}
    

    JSON逆シーケンス化器をカスタマイズします.
    public class CustomCarDeserializer extends StdDeserializer<Car> {
    
        public CustomCarDeserializer() {
            this(null);
        }
    
        public CustomCarDeserializer(Class<?> vc) {
            super(vc);
        }
    
        @Override
        public Car deserialize(JsonParser parser, DeserializationContext deserializer) throws IOException {
            Car car = new Car();
            ObjectCodec codec = parser.getCodec();
            JsonNode node = codec.readTree(parser);
    
            JsonNode colorNode = node.get("color");
            String color = colorNode.asText();
            car.setColor(color);
            return car;
        }
    }
    

    このカスタム逆シーケンス化器は、次のように呼び出すことができます.
            String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";
            ObjectMapper mapper = new ObjectMapper();
    
            SimpleModule module = new SimpleModule("CustomCarDeserializer", new Version(1, 0, 0, null, null, null));
            module.addDeserializer(Car.class, new CustomCarDeserializer());
            mapper.registerModule(module);
    
            Car car = mapper.readValue(json, Car.class);
            System.out.println(car); // Car    color    
    

    4.3. 日付フォーマットの処理java.util.Dateのデフォルトのシーケンス化は、紀元タイムスタンプ(1970年1月1日からUTC単位のミリ秒数)という数字を生成します.しかし、これは人間が読むことができるものではなく、さらに人間が読むことができるフォーマットで表示する必要がある.クラスを定義します.
    public class Request 
    {
        private Car car;
        private Date datePurchased;
     
        // getters/setters
    }
    

    日付を付けない処理の場合
            final ObjectMapper objectMapper = new ObjectMapper();
            final Car car = new Car("yellow", "renault");
            final Request request = new Request();
            request.setCar(car);
            request.setDatePurchased(new Date());
    
            String value = objectMapper.writeValueAsString(request);
            System.out.println(value); 
    // {"car":{"color":"yellow","type":"renault"},"datePurchased":1583050561145}
    

    日付フォーマット処理の追加
            final ObjectMapper objectMapper = new ObjectMapper();
            final Car car = new Car("yellow", "renault");
            final Request request = new Request();
            request.setCar(car);
            request.setDatePurchased(new Date());
    
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm a z");
            objectMapper.setDateFormat(df);
    
            String value = objectMapper.writeValueAsString(request);
            System.out.println(value);
    // {"car":{"color":"yellow","type":"renault"},"datePurchased":"2020-03-01 16:18    CST"}
    

    4.4. コレクションの処理DeserializationFeatureクラスが提供するもう一つの小さな有用な機能は、JSON Arrayから必要なタイプの集合を生成できる機能である.たとえば、Jsonを配列として生成できます.
            String jsonCarArray = "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]";
            ObjectMapper objectMapper = new ObjectMapper();
            
            objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true);
            Car[] cars = objectMapper.readValue(jsonCarArray, Car[].class);
    
            System.out.println(cars);
    

    またはJava Listに変換
    String jsonCarArray = 
      "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]";
    ObjectMapper objectMapper = new ObjectMapper();
    List<Car> listCar = objectMapper.readValue(jsonCarArray, new TypeReference<List<Car>>(){});