왜 잭슨 2는 첫 번째 대문자를 인식하지 못하는가? 낙타의 경우 단어 길이가 한 글자밖에 되지 않는데?
저는 잭슨2와 함께 봄4 MVC를 사용하고 있습니다.작업 중 하나에 대해 선두 camel case 워드의 길이가 1글자에 불과한 속성을 가진 요청 개체가 있습니다.
private String aLogId;
이 클래스에는 적절한 이름의 getter와 setter가 있습니다.
public String getALogId() { return aLogId; }
public void setALogId(String aLogId) { this.aLogId = aLogId; }
단, 대응하는 JSON 속성을 사용하여 이 서비스에 요청을 게시하려고 하면 다음과 같이 됩니다.
{"aLogId":"This is a log id"}
Spring 프레임워크에서 필드가 인식되지 않으며 컨트롤러 클래스가 호출되지 않는다는 500개의 응답을 받았습니다.
JSON을 읽을 수 없음: 인식할 수 없는 필드 "aLogId"(클래스)
단, "L"을 소문자로 변경하면 요구는 예상대로 역직렬화되어 컨트롤러 클래스가 히트합니다.
{"alogId":"This is a log id"}
속성에 대한 카멜 케이스 표기법에서 두 번째 단어인 "L"이 대문자여야 하는데 잭슨은 왜 소문자가 될 것으로 예상합니까?첫 글자가 한 글자라서 그런가?
요청 오브젝트에는 첫 번째 단어가 여러 글자로 되어 있으며, 이러한 Atribute는 Mismatch와 같은 문제에 직면하지 않는 다른 Atribute가 있습니다.
Jackson이 Java 클래스의 Json 속성을 파악하기 위해 Java Bean 명명 규칙을 사용했기 때문입니다.
여기 보이는 특정 문제에 대한 참조가 있습니다.사용하시는 필드에서는 처음 두 글자를 대문자로 사용하지 않는 것이 좋습니다.IntelliJ나 이클립스등의 IDE 를 사용하고, IDE 가 세터를 생성하도록 하면, 같은 「동작」이 발생하는 것을 알 수 있습니다.결국 다음과 같은 방법이 사용됩니다.
public void setaLogId(String aLogId) {
this.aLogId = aLogId;
}
public String getaLogId() {
return aLogId;
}
따라서 "L"을 소문자로 변경하면 Jackson은 매핑하려는 필드를 알아낼 수 있었습니다.
위에서 설명한 바와 같이, "aLogId" 필드 이름을 사용하여 잭슨에게 작업을 시킬 수 있는 다른 방법은@JsonProperty를 사용한 주석aLogId그 안에 있어요.
@JsonProperty("aLogId")
private String aLogId;
다음의 테스트 코드는, 이 동작의 구조를 나타내고 있습니다.
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Test {
@JsonProperty("aLogId")
private String aLogId;
public void setaLogId(String aLogId) {
this.aLogId = aLogId;
}
public String getaLogId() {
return aLogId;
}
public static void main(String[] args) {
ObjectMapper objectMapper = new ObjectMapper();
Test test = new Test();
test.setaLogId("anId");
try {
System.out.println("Serialization test: " + objectMapper.writeValueAsString(test));
String json = "{\"aLogId\":\"anotherId\"}";
Test anotherTest = objectMapper.readValue(json, Test.class);
System.out.println("Deserialization test: " +anotherTest.getaLogId());
} catch (Exception e) {
e.printStackTrace();
}
}
}
테스트의 출력은 다음과 같습니다.
Serialization test: {"aLogId":"anId"}
Deserialization test: anotherId
@JsonProperty현재 답변에서 제시된 바와 같이 모든 속성에 대해 반복해야 하고 침습적이라는 단점이 있습니다(지도화 중인 클래스를 변경해야 함).
보다 일반적인 접근법은 커스텀 속성 명명 전략을 제공하는 것입니다.
자바:
public class CustomSnakeCase extends PropertyNamingStrategy.PropertyNamingStrategyBase {
private static final Pattern REGEX = Pattern.compile("[A-Z]");
@Override
public String translate(String input) {
if (input == null)
return input; // garbage in, garbage out
if (!input.isEmpty() && Character.isUpperCase(input.charAt(0)))
input = input.substring(0, 1).toLowerCase() + input.substring(1);
return REGEX.matcher(input).replaceAll("_$0").toLowerCase();
}
}
코틀린:
class CustomSnakeCase : PropertyNamingStrategy.PropertyNamingStrategyBase() {
private companion object {
val REGEX = Regex("[A-Z]")
}
override fun translate(input: String?) =
input?.decapitalize()?.replace(REGEX, "_$0")?.toLowerCase()
}
사용방법:
new ObjectMapper()
.setPropertyNamingStrategy(new CustomSnakeCase())
.enable(MapperFeature.USE_STD_BEAN_NAMING)
주의: 위에서 설명한 구현에서는 입력이 다음과 같은 것을 전제로 하고 있습니다.camelCase( ( ( ( ( ( 。 USE_STD_BEAN_NAMING는, 「」, 「보다」의 1 문자 프리픽스를 합니다.aField일관되게
구현에서는 다음과 같은 매핑이 제공되므로 필요에 따라 매핑을 조정할 수 있습니다.
camelCase snake_case
----------------------------
simple simple
a a
sepaRated sepa_rated
iOException i_o_exception
xOffset x_offset
theWWW the_w_w_w
sepaRated32 sepa_rated32
sepa32Rated sepa32_rated
이것은 나에게 효과가 있었습니다; getters의 @JsonProperty 주석!
import com.fasterxml.jackson.annotation.JsonProperty;
public class PaytmRequestJson {
private String ORDERID;
private String MID;
private String CHECKSUMHASH;
@JsonProperty("ORDERID")
public String getORDERID() {
return ORDERID;
}
public void setORDERID(String ORDERID) {
this.ORDERID = ORDERID;
}
@JsonProperty("MID")
public String getMID() {
return MID;
}
public void setMID(String MID) {
this.MID = MID;
}
@JsonProperty("CHECKSUMHASH")
public String getCHECKSUMHASH() {
return CHECKSUMHASH;
}
public void setCHECKSUMHASH(String CHECKSUMHASH) {
this.CHECKSUMHASH = CHECKSUMHASH;
}
}
Jackson은 기본적으로 Java Bean 명명 규칙에 매우 가깝지만 완전히 동일하지는 않은 자체 명명 규칙을 사용합니다.Mapper Feature 옵션인 Mapper Feature.USE_STD_BEAN_NAMING은 잭슨에게 Java Bean 명명 규칙을 사용하도록 지시하기 위해 잭슨 2.5.0에 추가되었습니다.잭슨 이슈 653을 참조하십시오.하위 호환성을 위해 MapperFeature 기본값입니다.USE_STD_BEAN_NAMING이 false입니다.
코틀린에게도 같은 문제가 있어요접근자 메서드에 대한 @JsonProperty 주석을 사용하여 해결합니다.
예: @get:Json Property()ID") val ID: String = " "
필드 을 붙입니다. @JacksonXmlProperty(localName = "MsgType") 해 왔다
예
@JacksonXmlProperty(localName = "MsgType")
private String MsgType;
「」를 .@Jacksonized's Lombok's Lombok's를 가 있습니다.@Builder/@SuperBuilder.
언급URL : https://stackoverflow.com/questions/30205006/why-does-jackson-2-not-recognize-the-first-capital-letter-if-the-leading-camel-c
'programing' 카테고리의 다른 글
| AngularJs의 날짜 필터별 내림차순 (0) | 2023.03.11 |
|---|---|
| Redux에서는 상세 복사가 필요합니까? (0) | 2023.03.11 |
| Angular 체크박스와 ng클릭 (0) | 2023.03.11 |
| MongoDB가 모든 쿼리를 로깅합니다. (0) | 2023.03.11 |
| 2012년에 권장되는 jQuery 템플릿은 무엇입니까? (0) | 2023.03.11 |