【Jackson】ObjectMapper変換パターンいろいろ

## 環境
+ Java: 17
+ Spring Boot: 3.2.4 

## マッピングするentity, dto
```java:JacksonEntity.java
package com.example.demo.entity;

import java.util.Date;

import com.fasterxml.jackson.annotation.JsonAlias;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;

import lombok.Data;

@Data
public class JacksonEntity {

    private Integer id;

    private String name;

    @JsonIgnore
    @JsonAlias({"dept_id"})
    private Integer deptId;

    private String email;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonAlias({"updated_date"})
    private Date updatedDate;
}
```

```java:JacksonDto.java
package com.example.demo.dto;

import java.util.Date;

import com.fasterxml.jackson.annotation.JsonFormat;

import lombok.Data;

@Data
public class JacksonDto {

    private Integer id;

    private String name;

    private Integer deptId;

    private String deptName;

    private String email;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updatedDate;
}
```

## シンプルなjsonからentityへの変換

```java:java
String json
    = "{"
    + "       \"id\": 1,"
    + "       \"name\": \"田中花子\","
    + "       \"dept_id\": 1,"
    + "       \"deleted\": false,"
    + "       \"updated_date\": \"2024-01-01 00:00:00\""
    + "}";

  JacksonEntity jacksonEntity = objectMapper.reader()
          .forType(JacksonEntity.class)
          .readValue(json);

  System.out.println(jacksonEntity);
```

```:出力
JacksonEntity(id=1, name=田中花子, deptId=null, email=null, updatedDate=Mon Jan 01 09:00:00 JST 2024)
```

## シンプルなネストされたjsonからentityへの変換
```java:java
String json
    = "{"
    + "    \"data\": "
    + "        {"
    + "            \"id\": 1,"
    + "            \"name\": \"田中花子\","
    + "            \"dept_id\": 1,"
    + "            \"deleted\": false,"
    + "            \"updated_date\": \"2024-01-01 00:00:00\""
    + "        }"
    + "}";

  JacksonEntity jacksonEntity = objectMapper.reader()
          .withRootName("data")
          .forType(JacksonEntity.class)
          .readValue(json);

  System.out.println(jacksonEntity);
```

```:出力
JacksonEntity(id=1, name=田中花子, deptId=null, email=null, updatedDate=Mon Jan 01 09:00:00 JST 2024)
```

## シンプルなネストされたjsonからentityのリストへの変換
```java:java
String json
    = "{"
    + "    \"data\": ["
    + "        {"
    + "            \"id\": 1,"
    + "            \"name\": \"田中花子\","
    + "            \"dept_id\": 1,"
    + "            \"deleted\": false,"
    + "            \"updated_date\": \"2024-01-01 00:00:00\""
    + "        },"
    + "        {"
    + "            \"id\": 2,"
    + "            \"name\": \"山田次郎\","
    + "            \"dept_id\": 1,"
    + "            \"deleted\": true,"
    + "            \"updated_date\": \"2024-01-01 00:00:00\""
    + "        }"
    + "    ]"
    + "}";

Map<String, Object> jsonMap = objectMapper.readValue(json, new TypeReference<Map<String, Object>>(){});
List<JacksonEntity> jacksonEntities = objectMapper.convertValue(jsonMap.get("data"), new TypeReference<List<JacksonEntity>>() {});

jacksonEntities.forEach(System.out::println);
```

```:出力
JacksonEntity(id=1, name=田中花子, deptId=null, email=null, updatedDate=Mon Jan 01 09:00:00 JST 2024)
JacksonEntity(id=2, name=山田次郎, deptId=null, email=null, updatedDate=Mon Jan 01 09:00:00 JST 2024)
```

## ネストされたjsonからentityへの変換
```java:java
String json
    = "{"
    + "    \"data\": "
    + "        {"
    + "            \"id\": 1,"
    + "            \"name\": \"田中花子\","
    + "            \"dept_id\": 1,"
    + "            \"deleted\": false,"
    + "            \"updated_date\": \"2024-01-01 00:00:00\""
    + "        },"
    + "    \"success\": true"
    + "}";

Map<String, Object> jsonMap = objectMapper.readValue(json, new TypeReference<Map<String, Object>>(){});
JacksonEntity jacksonEntity = objectMapper.convertValue(jsonMap.get("data"), JacksonEntity.class);

System.out.println(jacksonEntity);
```

```:出力
JacksonEntity(id=1, name=田中花子, deptId=null, email=null, updatedDate=Mon Jan 01 09:00:00 JST 2024)
```

## ネストされたjsonからentityへの変換（JsonNode使用）
```java:java
String json
    = "{"
    + "    \"data\": "
    + "        {"
    + "            \"id\": 1,"
    + "            \"name\": \"田中花子\","
    + "            \"dept_id\": 1,"
    + "            \"deleted\": false,"
    + "            \"updated_date\": \"2024-01-01 00:00:00\""
    + "        },"
    + "    \"success\": true"
    + "}";

JsonNode root = objectMapper.readTree(json);
JacksonEntity jacksonEntity = objectMapper.convertValue(root.at("/data"), JacksonEntity.class);

System.out.println(jacksonEntity);
```

```:出力
JacksonEntity(id=1, name=田中花子, deptId=null, email=null, updatedDate=Mon Jan 01 09:00:00 JST 2024)
```

## ネストされたjsonからentityのリストへの変換
```java:java
String json
    = "{"
    + "    \"data\": ["
    + "        {"
    + "            \"id\": 1,"
    + "            \"name\": \"田中花子\","
    + "            \"dept_id\": 1,"
    + "            \"deleted\": false,"
    + "            \"updated_date\": \"2024-01-01 00:00:00\""
    + "        },"
    + "        {"
    + "            \"id\": 2,"
    + "            \"name\": \"山田次郎\","
    + "            \"dept_id\": 1,"
    + "            \"deleted\": true,"
    + "            \"updated_date\": \"2024-01-02 00:00:00\""
    + "        }"
    + "    ],"
    + "    \"success\": true"
    + "}";

Map<String, Object> jsonMap = objectMapper.readValue(json, new TypeReference<Map<String, Object>>(){});
List<JacksonEntity> jacksonEntities = objectMapper.convertValue(jsonMap.get("data"), new TypeReference<List<JacksonEntity>>() {});

jacksonEntities.forEach(System.out::println);
```

```:出力
JacksonEntity(id=1, name=田中花子, deptId=null, email=null, updatedDate=Mon Jan 01 09:00:00 JST 2024)
JacksonEntity(id=2, name=山田次郎, deptId=null, email=null, updatedDate=Tue Jan 02 09:00:00 JST 2024)
```

## entityからdtoへの変換
```java:java
JacksonEntity jacksonEntity = new JacksonEntity();
jacksonEntity.setId(1);
jacksonEntity.setName("田中花子");
jacksonEntity.setDeptId(1);
jacksonEntity.setEmail("hanako.tanaka@example.co.jp");
jacksonEntity.setUpdatedDate(new Date());

JacksonDto jacksonDto = objectMapper.convertValue(jacksonEntity, JacksonDto.class);

System.out.println(jacksonDto);
```

```:出力
JacksonDto(id=1, name=田中花子, deptId=null, deptName=null, email=hanako.tanaka@example.co.jp, updatedDate=Fri May 31 23:29:00 JST 2024)
```

## dtoからentityへの変換
```java:java
JacksonDto jacksonDto = new JacksonDto();
jacksonDto.setId(1);
jacksonDto.setName("田中花子");
jacksonDto.setDeptId(1);
jacksonDto.setDeptName("営業部");
jacksonDto.setEmail("hanako.tanaka@example.co.jp");
jacksonDto.setUpdatedDate(new Date());

JacksonEntity jacksonEntity = objectMapper.convertValue(jacksonDto, JacksonEntity.class);

System.out.println(jacksonEntity);
```

```:出力
JacksonEntity(id=1, name=田中花子, deptId=null, email=hanako.tanaka@example.co.jp, updatedDate=Fri May 31 23:29:00 JST 2024)
```

## entityのリストからdtoのリストへの変換
```java:java
List<JacksonEntity> jacksonEntities = new ArrayList<>();
JacksonEntity jacksonEntity = new JacksonEntity();
jacksonEntity.setId(1);
jacksonEntity.setName("田中花子");
jacksonEntity.setDeptId(1);
jacksonEntity.setEmail("hanako.tanaka@example.co.jp");
jacksonEntity.setUpdatedDate(new Date());
jacksonEntities.add(jacksonEntity);
jacksonEntity = new JacksonEntity();
jacksonEntity.setId(2);
jacksonEntity.setName("山田太郎");
jacksonEntity.setDeptId(1);
jacksonEntity.setEmail("taro.yamada@example.co.jp");
jacksonEntity.setUpdatedDate(new Date());
jacksonEntities.add(jacksonEntity);

List<JacksonDto> jacksonDtos = objectMapper.convertValue(jacksonEntities, new TypeReference<List<JacksonDto>>(){});

jacksonDtos.forEach(System.out::println);
```

```:出力
JacksonDto(id=1, name=田中花子, deptId=null, deptName=null, email=hanako.tanaka@example.co.jp, updatedDate=Fri May 31 23:29:00 JST 2024)
JacksonDto(id=2, name=山田太郎, deptId=null, deptName=null, email=taro.yamada@example.co.jp, updatedDate=Fri May 31 23:29:00 JST 2024)
```

## dtoのリストからentityのリストへの変換
```java:java
List<JacksonDto> jacksonDtos = new ArrayList<>();
JacksonDto jacksonDto = new JacksonDto();
jacksonDto.setId(1);
jacksonDto.setName("田中花子");
jacksonDto.setDeptId(1);
jacksonDto.setDeptName("営業部");
jacksonDto.setEmail("hanako.tanaka@example.co.jp");
jacksonDto.setUpdatedDate(new Date());
jacksonDtos.add(jacksonDto);
jacksonDto = new JacksonDto();
jacksonDto.setId(2);
jacksonDto.setName("山田太郎");
jacksonDto.setDeptId(1);
jacksonDto.setDeptName("営業部");
jacksonDto.setEmail("taro.yamada@example.co.jp");
jacksonDto.setUpdatedDate(new Date());
jacksonDtos.add(jacksonDto);

List<JacksonEntity> jacksonEntities = objectMapper.convertValue(jacksonDtos, new TypeReference<List<JacksonEntity>>(){});

jacksonEntities.forEach(System.out::println);
```

```:出力
JacksonEntity(id=1, name=田中花子, deptId=null, email=hanako.tanaka@example.co.jp, updatedDate=Fri May 31 23:29:00 JST 2024)
JacksonEntity(id=2, name=山田太郎, deptId=null, email=taro.yamada@example.co.jp, updatedDate=Fri May 31 23:29:00 JST 2024)
```

## コード全体

```java:JacksonService.java
package com.example.demo.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.demo.dto.JacksonDto;
import com.example.demo.entity.JacksonEntity;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class JacksonService {

    @Autowired
    private ObjectMapper objectMapper;

    public void simpleJsonToEntity() throws JsonMappingException, JsonProcessingException {
        log.info("Simple Json to Entity");

        String json
            = "{"
            + "       \"id\": 1,"
            + "       \"name\": \"田中花子\","
            + "       \"dept_id\": 1,"
            + "       \"deleted\": false,"
            + "       \"updated_date\": \"2024-01-01 00:00:00\""
            + "}";

          JacksonEntity jacksonEntity = objectMapper.reader()
                  .forType(JacksonEntity.class)
                  .readValue(json);

          System.out.println(jacksonEntity);
          // JacksonEntity(id=1, name=田中花子, deptId=null, email=null, updatedDate=Mon Jan 01 09:00:00 JST 2024)
    }

    public void simpleNestedJsonToEntity() throws JsonMappingException, JsonProcessingException {
        log.info("Simple Nested Json to Entity");

        String json
            = "{"
            + "    \"data\": "
            + "        {"
            + "            \"id\": 1,"
            + "            \"name\": \"田中花子\","
            + "            \"dept_id\": 1,"
            + "            \"deleted\": false,"
            + "            \"updated_date\": \"2024-01-01 00:00:00\""
            + "        }"
            + "}";

          JacksonEntity jacksonEntity = objectMapper.reader()
                  .withRootName("data")
                  .forType(JacksonEntity.class)
                  .readValue(json);

          System.out.println(jacksonEntity);
          // JacksonEntity(id=1, name=田中花子, deptId=null, email=null, updatedDate=Mon Jan 01 09:00:00 JST 2024)
    }

    public void simpleNestedJsonToEntityList() throws JsonMappingException, JsonProcessingException {
        log.info("Simple Nested Json to Entity List");

        String json
            = "{"
            + "    \"data\": ["
            + "        {"
            + "            \"id\": 1,"
            + "            \"name\": \"田中花子\","
            + "            \"dept_id\": 1,"
            + "            \"deleted\": false,"
            + "            \"updated_date\": \"2024-01-01 00:00:00\""
            + "        },"
            + "        {"
            + "            \"id\": 2,"
            + "            \"name\": \"山田次郎\","
            + "            \"dept_id\": 1,"
            + "            \"deleted\": true,"
            + "            \"updated_date\": \"2024-01-01 00:00:00\""
            + "        }"
            + "    ]"
            + "}";

        Map<String, Object> jsonMap = objectMapper.readValue(json, new TypeReference<Map<String, Object>>(){});
        List<JacksonEntity> jacksonEntities = objectMapper.convertValue(jsonMap.get("data"), new TypeReference<List<JacksonEntity>>() {});

        jacksonEntities.forEach(System.out::println);
        // JacksonEntity(id=1, name=田中花子, deptId=null, email=null, updatedDate=Mon Jan 01 09:00:00 JST 2024)
        // JacksonEntity(id=2, name=山田次郎, deptId=null, email=null, updatedDate=Mon Jan 01 09:00:00 JST 2024)
    }

    public void nestedJsonToEntity() throws JsonMappingException, JsonProcessingException {
        log.info("Nested Json to Entity");

        String json
            = "{"
            + "    \"data\": "
            + "        {"
            + "            \"id\": 1,"
            + "            \"name\": \"田中花子\","
            + "            \"dept_id\": 1,"
            + "            \"deleted\": false,"
            + "            \"updated_date\": \"2024-01-01 00:00:00\""
            + "        },"
            + "    \"success\": true"
            + "}";

        Map<String, Object> jsonMap = objectMapper.readValue(json, new TypeReference<Map<String, Object>>(){});
        JacksonEntity jacksonEntity = objectMapper.convertValue(jsonMap.get("data"), JacksonEntity.class);

        System.out.println(jacksonEntity);
        // JacksonEntity(id=1, name=田中花子, deptId=null, email=null, updatedDate=Mon Jan 01 09:00:00 JST 2024)
    }

    public void nestedJsonToEntityWithJsonNode() throws JsonMappingException, JsonProcessingException {
        log.info("Nested Json to Entity with JsonNode");

        String json
            = "{"
            + "    \"data\": "
            + "        {"
            + "            \"id\": 1,"
            + "            \"name\": \"田中花子\","
            + "            \"dept_id\": 1,"
            + "            \"deleted\": false,"
            + "            \"updated_date\": \"2024-01-01 00:00:00\""
            + "        },"
            + "    \"success\": true"
            + "}";

        JsonNode root = objectMapper.readTree(json);
        JacksonEntity jacksonEntity = objectMapper.convertValue(root.at("/data"), JacksonEntity.class);

        System.out.println(jacksonEntity);
        // JacksonEntity(id=1, name=田中花子, deptId=null, email=null, updatedDate=Mon Jan 01 09:00:00 JST 2024)
    }

    public void nestedJsonToEntityList() throws JsonMappingException, JsonProcessingException {
        log.info("Nested Json to Entity List");

        String json
            = "{"
            + "    \"data\": ["
            + "        {"
            + "            \"id\": 1,"
            + "            \"name\": \"田中花子\","
            + "            \"dept_id\": 1,"
            + "            \"deleted\": false,"
            + "            \"updated_date\": \"2024-01-01 00:00:00\""
            + "        },"
            + "        {"
            + "            \"id\": 2,"
            + "            \"name\": \"山田次郎\","
            + "            \"dept_id\": 1,"
            + "            \"deleted\": true,"
            + "            \"updated_date\": \"2024-01-02 00:00:00\""
            + "        }"
            + "    ],"
            + "    \"success\": true"
            + "}";

        Map<String, Object> jsonMap = objectMapper.readValue(json, new TypeReference<Map<String, Object>>(){});
        List<JacksonEntity> jacksonEntities = objectMapper.convertValue(jsonMap.get("data"), new TypeReference<List<JacksonEntity>>() {});

        jacksonEntities.forEach(System.out::println);
        // JacksonEntity(id=1, name=田中花子, deptId=null, email=null, updatedDate=Mon Jan 01 09:00:00 JST 2024)
        // JacksonEntity(id=2, name=山田次郎, deptId=null, email=null, updatedDate=Tue Jan 02 09:00:00 JST 2024)
    }

    public void entityToDto() throws JsonMappingException, JsonProcessingException {
        log.info("Entity to Dto");

        JacksonEntity jacksonEntity = new JacksonEntity();
        jacksonEntity.setId(1);
        jacksonEntity.setName("田中花子");
        jacksonEntity.setDeptId(1);
        jacksonEntity.setEmail("hanako.tanaka@example.co.jp");
        jacksonEntity.setUpdatedDate(new Date());

        JacksonDto jacksonDto = objectMapper.convertValue(jacksonEntity, JacksonDto.class);

        System.out.println(jacksonDto);
        // JacksonDto(id=1, name=田中花子, deptId=null, deptName=null, email=hanako.tanaka@example.co.jp, updatedDate=Fri May 31 23:29:00 JST 2024)
    }

    public void dtoToEntity() throws JsonMappingException, JsonProcessingException {
        log.info("Dto to Entity");

        JacksonDto jacksonDto = new JacksonDto();
        jacksonDto.setId(1);
        jacksonDto.setName("田中花子");
        jacksonDto.setDeptId(1);
        jacksonDto.setDeptName("営業部");
        jacksonDto.setEmail("hanako.tanaka@example.co.jp");
        jacksonDto.setUpdatedDate(new Date());

        JacksonEntity jacksonEntity = objectMapper.convertValue(jacksonDto, JacksonEntity.class);

        System.out.println(jacksonEntity);
        // JacksonEntity(id=1, name=田中花子, deptId=null, email=hanako.tanaka@example.co.jp, updatedDate=Fri May 31 23:29:00 JST 2024)
    }

    public void entityListToDtoList() throws JsonMappingException, JsonProcessingException {
        log.info("Entity List to Dto List");

        List<JacksonEntity> jacksonEntities = new ArrayList<>();
        JacksonEntity jacksonEntity = new JacksonEntity();
        jacksonEntity.setId(1);
        jacksonEntity.setName("田中花子");
        jacksonEntity.setDeptId(1);
        jacksonEntity.setEmail("hanako.tanaka@example.co.jp");
        jacksonEntity.setUpdatedDate(new Date());
        jacksonEntities.add(jacksonEntity);
        jacksonEntity = new JacksonEntity();
        jacksonEntity.setId(2);
        jacksonEntity.setName("山田太郎");
        jacksonEntity.setDeptId(1);
        jacksonEntity.setEmail("taro.yamada@example.co.jp");
        jacksonEntity.setUpdatedDate(new Date());
        jacksonEntities.add(jacksonEntity);

        List<JacksonDto> jacksonDtos = objectMapper.convertValue(jacksonEntities, new TypeReference<List<JacksonDto>>(){});

        jacksonDtos.forEach(System.out::println);
        // JacksonDto(id=1, name=田中花子, deptId=null, deptName=null, email=hanako.tanaka@example.co.jp, updatedDate=Fri May 31 23:29:00 JST 2024)
        // JacksonDto(id=2, name=山田太郎, deptId=null, deptName=null, email=taro.yamada@example.co.jp, updatedDate=Fri May 31 23:29:00 JST 2024)
    }

    public void dtoListToEntityList() throws JsonMappingException, JsonProcessingException {
        log.info("Dto List to Entity List");

        List<JacksonDto> jacksonDtos = new ArrayList<>();
        JacksonDto jacksonDto = new JacksonDto();
        jacksonDto.setId(1);
        jacksonDto.setName("田中花子");
        jacksonDto.setDeptId(1);
        jacksonDto.setDeptName("営業部");
        jacksonDto.setEmail("hanako.tanaka@example.co.jp");
        jacksonDto.setUpdatedDate(new Date());
        jacksonDtos.add(jacksonDto);
        jacksonDto = new JacksonDto();
        jacksonDto.setId(2);
        jacksonDto.setName("山田太郎");
        jacksonDto.setDeptId(1);
        jacksonDto.setDeptName("営業部");
        jacksonDto.setEmail("taro.yamada@example.co.jp");
        jacksonDto.setUpdatedDate(new Date());
        jacksonDtos.add(jacksonDto);

        List<JacksonEntity> jacksonEntities = objectMapper.convertValue(jacksonDtos, new TypeReference<List<JacksonEntity>>(){});

        jacksonEntities.forEach(System.out::println);
        // JacksonEntity(id=1, name=田中花子, deptId=null, email=hanako.tanaka@example.co.jp, updatedDate=Fri May 31 23:29:00 JST 2024)
        // JacksonEntity(id=2, name=山田太郎, deptId=null, email=taro.yamada@example.co.jp, updatedDate=Fri May 31 23:29:00 JST 2024)
    }
}
```