何があったの?
SpringBootでWebAPIを作って、HTTPリクエストでJSONを飛ばしたら、なんかJSONのキーが大文字の時だけControllerの引数にパースできずにNullになってしまったよ。
JSONのキーを小文字にしたらなんか行けた。なんでや。
もう上司に「大文字でやるわ」って仕様書出しちゃったから今から「やっぱり小文字にしたいっす」って言いにくい。なんとかして。
解決策
application.propertiesに下記一行追加するだけ。
大文字小文字関係なくパースしてくれるようになるよ。
やや大味な解決策だけど、まぁ大丈夫でしょ。
spring.jackson.mapper.ACCEPT_CASE_INSENSITIVE_PROPERTIES=true
確認
バージョン
SpringBoot: 3.2.4
デフォルトの確認
spring.application.name=demo
# spring.jackson.mapper.ACCEPT_CASE_INSENSITIVE_PROPERTIES=true 解決策をコメントアウト
package com.example.demo;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/OtaAPI")
public class Otacon {
@PostMapping("/json2api")
public ResponseEntity<String> json1(@RequestBody Input2 input) {
return ResponseEntity.ok(enabled() + input.toString());
}
private String enabled() {
ObjectMapper objectMapper = new ObjectMapper();
boolean accept = objectMapper.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES);
String result = "***ACCEPT_CASE_INSENSITIVE_PROPERTIES:" + (accept ? "true": "false") + "*** ";
return result;
}
@Data
public static class Input2 {
private Inner key1;
private String KEY2;
}
@Data
public static class Inner {
private String key1_1;
private String KEY1_2;
}
}
>curl http://localhost:8080/OtaAPI/json2api -X POST -d "{\"key1\":{\"key1_1\":\"キー1\",\"key1_2\":\"キー1_2\"},\"key2\":\"キー2\"}" -H "Content-Type: application/json"
***ACCEPT_CASE_INSENSITIVE_PROPERTIES:false*** Otacon.Input2(key1=Otacon.Inner(key1_1=キー1, KEY1_2=キー1_2), KEY2=キー2)
>curl http://localhost:8080/OtaAPI/json2api -X POST -d "{\"KEY1\":{\"KEY1_1\":\"キー1\",\"KEY1_2\":\"キー1_2\"},\"KEY2\":\"キー2\"}" -H "Content-Type: application/json"
***ACCEPT_CASE_INSENSITIVE_PROPERTIES:false*** Otacon.Input2(key1=null, KEY2=null)
- JSONのキーとJavaフィールド名の大文字小文字を合わせないとパースできないよ
- SpringBootはデフォルトで大文字小文字の区別は無視する設定だから大丈夫だよ
という説明をどこかで見た気がするが、いずれも間違っていることが確認できたよ。
実証結果として、デフォルトでは以下の通りの動きとなった。
- JSONのキーとJavaフィールド名は、大文字小文字の区別なくパースしてくれるよ。
- JSONのキーが大文字の時は、Javaフィールド名がどうあろうとパースはしないよ。
application.propertiesに設定した場合の確認
spring.application.name=demo
spring.jackson.mapper.ACCEPT_CASE_INSENSITIVE_PROPERTIES=true
// 変更ないので省略するよ
>curl http://localhost:8080/OtaAPI/json2api -X POST -d "{\"key1\":{\"key1_1\":\"キー1\",\"key1_2\":\"キー1_2\"},\"key2\":\"キー2\"}" -H "Content-Type: application/json"
***ACCEPT_CASE_INSENSITIVE_PROPERTIES:false*** Otacon.Input2(key1=Otacon.Inner(key1_1=キー1, KEY1_2=キー1_2), KEY2=キー2)
>curl http://localhost:8080/OtaAPI/json2api -X POST -d "{\"KEY1\":{\"KEY1_1\":\"キー1\",\"KEY1_2\":\"キー1_2\"},\"KEY2\":\"キー2\"}" -H "Content-Type: application/json"
***ACCEPT_CASE_INSENSITIVE_PROPERTIES:false*** Otacon.Input2(key1=Otacon.Inner(key1_1=キー1, KEY1_2=キー1_2), KEY2=キー2)
spring.jackson.mapper.ACCEPT_CASE_INSENSITIVE_PROPERTIES=true
を設定することで以下の通りとなった
- JSONのキーとJavaフィールド名は、大文字小文字の区別なくパースしてくれるよ。
- JSONのキーが大文字の時もパースしてくれるよ。
蛇足
application.propertiesで上記設定を有効にすると、
ObjectMapper objectMapper = new ObjectMapper();
boolean accept = objectMapper.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES);
で true が返るものだと思っていたけど、違ったみたい。
意味なかったねこのコード。
おわるよ。