ObjectMapperを試してみた

# 概要

JavaのclassとJsonの変換に関して試したことを列挙します！

# 利用例

## JavaクラスからJson文字列への変換



```java
import lombok.AllArgsConstructor;
import lombok.Getter;

@AllArgsConstructor
@Getter
public class Response {
    String accessToken;
    String refreshToken;
}
```


```java
    @Test
    void オブジェクトをJsonに変換できる() throws Exception {
        // arrange
        var response = new Response("a", "b");

        // act, assert
        assertEquals("{\"accessToken\":\"a\",\"refreshToken\":\"b\"}",
                new ObjectMapper().writeValueAsString(response));
    }
```

## Json文字列からJavaクラスへの変換

```java
import lombok.*;

@AllArgsConstructor
@Getter
@EqualsAndHashCode
@NoArgsConstructor
public class Response {
    String accessToken;
    String refreshToken;
}
```

```java
    @Test
    void Jsonをオブジェクトに変換できる() throws Exception {
        // arrange
        var jsonString = "{\"accessToken\":\"a\",\"refreshToken\":\"b\"}";

        // act, assert
        assertEquals(new Response("a", "b"),
                new ObjectMapper().readValue(jsonString, Response.class));
    }

```


## JavaクラスからJson文字列への変換(スネークケース)

```java
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.AllArgsConstructor;
import lombok.Getter;

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
@AllArgsConstructor
@Getter
public class SnakeResponse {
    String accessToken; // フィールドをpublicにするのでもOK　
    String refreshToken;
}
```


```java
    @Test
    void オブジェクトをJsonにスネークケースで変換できる() throws Exception {
        // arrange
        var response = new SnakeResponse("a", "b");

        // act, assert
        assertEquals("{\"access_token\":\"a\",\"refresh_token\":\"b\"}",
                new ObjectMapper().writeValueAsString(response));
    }
```

### PropertyNamingStrategyのバリエーション

|Strategy|結果|
|---|---|
|LowerDotCaseStrategy|{"access.token":"a","refresh.token":"b"}|
|SnakeCaseStrategy|{"access_token":"a","refresh_token":"b"}|
|KebabCaseStrategy|{"access-token":"a","refresh-token":"b"}|
|LowerCaseStrategy|{"accesstoken":"a","refreshtoken":"b"}|
|UpperCamelCaseStrategy|{"AccessToken":"a","RefreshToken":"b"}|


## nullがある場合は表示しない
```java
@AllArgsConstructor
@Getter
@EqualsAndHashCode
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Response {
    String accessToken;
    String refreshToken;
}
```


```java

    @Test
    void オブジェクトにnullがある場合_そのプロパティは表示しない() throws Exception {
        // arrange
        var response = new Response("a", null);

        // act, assert
        assertEquals("{\"accessToken\":\"a\"}",
                new ObjectMapper().writeValueAsString(response));
    }
```




# エラー

## フィールドが見えない時のエラー
`No serializer found for class Response and no properties discovered to create BeanSerializer`はgetterをつければ解消できます。

```java
@AllArgsConstructor
//@Getter // ここがないからエラー もちろん自分でgetter作ってもOK
public class Response {
    String accessToken; // フィールドをpublicにするのでもOK　
    String refreshToken;
}
```

```java
    @Test
    void オブジェクトをJsonに変換できる() throws Exception {
        // arrange
        var response = new Response("a", "b");

        // act, assert
        assertEquals("{\"accessToken\":\"a\",\"refreshToken\":\"b\"}",
                new ObjectMapper().writeValueAsString(response));
    }
```


## コンストラクタがないエラー

`Cannot construct instance of Response (no Creators, like default constructor, exist): cannot deserialize from Object value`

```java
@AllArgsConstructor
@Getter
@EqualsAndHashCode
//@NoArgsConstructor // これがない
public class Response {
    String accessToken;
    String refreshToken;
}
```

```java
    @Test
    void Jsonをオブジェクトに変換できる() throws Exception {
        // arrange
        var jsonString = "{\"accessToken\":\"a\",\"refreshToken\":\"b\"}";

        // act, assert
        assertEquals(new Response("a", "b"),
                new ObjectMapper().readValue(jsonString, Response.class));
    }
```