Index
๋ฌธ์ ๋ฐ์
ํ๊ฐ๋ก์ด ์คํ ๊ฐ๋ฐํ๊ฒฝ์ api ์๋ต ์๋ฌ๊ฐ ๋๋ค๊ณ ๋ฌธ์๊ฐ ๋ค์ด์์ต๋๋ค.
ES์ ์๋ฌ ๋ก๊ทธ๋ฅผ ํ์ธํด๋ณด๋ ์ด๋ฌํ ์๋ฌ ๋ก๊ทธ๊ฐ.. ์ค์ค..
(์ค์ ํ๊ฒฝ์ ํฌ์คํ ํ ์ ์์ด ์์ ์ฝ๋๋ฅผ ์์ฑํ์ฌ ์๋ฌ๋ฅผ ์ ๋ํจ)
Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of `com.example.lomboktest.SampleDto` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator);
nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.example.lomboktest.SampleDto` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)<EOL> at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 2, column: 5]]
๋ฌธ์ ๊ฐ ๋ฐ์ํ dto๋ฅผ ํ์ธํด๋ด ์๋ค.
@Getter
public class SampleDto {
@Builder.Default
private String test = "tesT";
@Builder
public SampleDto(String test) {
this.test = test;
}
}
์.. ์์ฑ์๋ฅผ ์ ์ธํ๊ณ ๋น๋๋ฅผ ์ ์ธํ์๋๋ฐ ๋ฌด์์ด ๋ฌธ์ ์ผ๊น?
์๋ฌ ๋ก๊ทธ๋ฅผ ์์ธํ ํ์ธํด๋ด ์๋ค.
JSON parse error:
Cannot construct instance of `com.example.lomboktest.SampleDto`
(although at least one Creator exists):
cannot deserialize from Object value (no delegate- or property-based Creator);
์ง์ญํ์๋ฉด,
JSON ํ์ฑ ์๋ฌ
SampleDto๋ฅผ ์์ฑํ ์ ์๋ค.
(์ต์ ํ๊ฐ์ ์์ฑ์๊ฐ ์กด์ฌํ์ง๋ง)
๊ฐ์ฒด๊ฐ์ผ๋ก๋ถํฐ ์ญ์ง๋ ฌํ๋ฅผ ํ ์ ์๋ค. (delegate ๋๋ property ๊ธฐ๋ฐ์ ์์ฑ์๊ฐ ์์)
์ฌ์ค ๋ฑ ๋ณด์๋ง์ ์์๋ดค๋ค. ํ์ง๋ง ์ง์์ output์ ํด์ผ ์ค๋ ๊ธฐ์ต์ ๋จ๋๋ฒ.. ๊ทธ๋์ ์ ๋ฆฌํ๋ฉฐ ํฌ์คํ
ํ๋ค.
์์ฑ์๊ฐ ์กด์ฌํ๋๋ฐ, ์?
๋์น์ฑ์ ๋ถ๋ค์ ์์๊ฒ ์ง๋ง, spring์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ง๋ ฌํ/์ญ์ง๋ ฌํ์ ์ญ์จ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ธฐ๋ณธ์ผ๋ก ์ฌ์ฉํ๊ณ ์๊ณ ๊ทธ ์ญ์จ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๊ธฐ๋ณธ์์ฑ์๊ฐ ์์ผ๋ฉด ๋์ํ์ง ์์ต๋๋ค.
์, ์๋ฌ ๋ฉ์ธ์ง๋ฅผ ์ถ๋ ฅํ ํด๋์ค๋ฅผ ์ถ์ ํด๋ด ์๋ค.
protected Object deserializeFromObjectUsingNonDefault(JsonParser p,
DeserializationContext ctxt) throws IOException
{
final JsonDeserializer<Object> delegateDeser = _delegateDeserializer();
if (delegateDeser != null) {
final Object bean = _valueInstantiator.createUsingDelegate(ctxt,
delegateDeser.deserialize(p, ctxt));
if (_injectables != null) {
injectValues(ctxt, bean);
}
return bean;
}
if (_propertyBasedCreator != null) {
return _deserializeUsingPropertyBased(p, ctxt);
}
// 25-Jan-2017, tatu: We do not actually support use of Creators for non-static
// inner classes -- with one and only one exception; that of default constructor!
// -- so let's indicate it
Class<?> raw = _beanType.getRawClass();
if (ClassUtil.isNonStaticInnerClass(raw)) {
return ctxt.handleMissingInstantiator(raw, null, p,
"non-static inner classes like this can only by instantiated using default, no-argument constructor");
}
return ctxt.handleMissingInstantiator(raw, getValueInstantiator(), p,
"cannot deserialize from Object value (no delegate- or property-based Creator)");
}
์๋ฌ๋ก๊ทธ๋ฅผ ์ ๋ฌํ๋ ๋ฉ์๋ ์ด๋ฆ์ด deserializeFromObjectUsingNonDefault
์๋์ด๋ค.
์ด๋ฆ๋ถํฐ ์ฌ์์น์๋ค.
์ข๋ ์ฐพ์๋ณด์.
/*
/**********************************************************
/* Public API implementation; instantiation from JSON Object
/**********************************************************
*/
@Override
public Object createUsingDefault(DeserializationContext ctxt) throws IOException
{
if (_defaultCreator == null) { // sanity-check; caller should check
return super.createUsingDefault(ctxt);
}
try {
return _defaultCreator.call();
} catch (Exception e) { // 19-Apr-2017, tatu: Let's not catch Errors, just Exceptions
return ctxt.handleInstantiationProblem(_valueClass, null, rewrapCtorProblem(ctxt, e));
}
}
๋ฉ์๋๋ฅผ ๊พธ์คํ ๋ฐ๋ผ๊ฐ๋ค๋ณด๋ ๋ฌธ์ ๋ฐ์ ๊ทผ์์ง๋ฅผ ์ฐพ์ ์ ์์๋ค.
if (_defaultCreator == null) { // sanity-check; caller should check
์ด ๋ถ๋ถ์ด ๋ฐ๋ก ๊ธฐ๋ณธ์์ฑ์๊ฐ null ์ธ์ง ํ์ธํ๊ณ null์ด๋ฉด super.createUsingDefault(ctxt);
๋ฉ์๋๊ฐ ํธ์ถ๋ ๊ฒ์ด๊ณ ์๋ฌ๋ก๊ทธ๊ฐ ์ถ๋ ฅ๋ ๊ณณ์ผ๋ก ๋ฐ์ธ๋ฉ๋์ด ์ค์ ์๋ฌ๋ก๊ทธ๊ฐ ์ถ๋ ฅ๋ ๊ฒ์
๋๋ค.
๋ฐ๋๋ก ๊ธฐ๋ณธ์์ฑ์๊ฐ ์๋ค๋ฉด ํธ์ถ๋๋ _defaultCreator.call();
๋ฅผ ๋ค์ด๊ฐ๋ณด๋ฉด ๊ธฐ๋ณธ์์ฑ์๋ฅผ ์ฌ์ฉํ๋์ง ์ดํด๋ณด๋ฉด ํ์คํ ์ ์ ์์ ๊ฒ ๊ฐ๋ค์.
@Override
public final Object call() throws Exception {
// 31-Mar-2021, tatu: Note! This is faster than calling without arguments
// because JDK in its wisdom would otherwise allocate `new Object[0]` to pass
return _constructor.newInstance((Object[]) null);
}
๊ทธ๋ ๋ค๋ฉด ์๋ฌ๋ก๊ทธ์ ์๋ no delegate- or property-based ๋ ๋ญ์ง?
์ฐ๋ฆฌ๊ฐ ์ง๋์ณ์จ ์ฝ๋์ ๋ต์ด ์กด์ฌํฉ๋๋ค.
์์ ์ฝ๋ ์ค ์๋ฌ๋ฉ์ธ์ง ์ถ๋ ฅ๋ ๋ฉ์๋๋ฅผ ํ์ธํด๋ณผ๊น์?
protected Object deserializeFromObjectUsingNonDefault(JsonParser p,
DeserializationContext ctxt) throws IOException
{
final JsonDeserializer<Object> delegateDeser = _delegateDeserializer();
if (delegateDeser != null) {
final Object bean = _valueInstantiator.createUsingDelegate(ctxt,
delegateDeser.deserialize(p, ctxt));
if (_injectables != null) {
injectValues(ctxt, bean);
}
return bean;
}
if (_propertyBasedCreator != null) {
return _deserializeUsingPropertyBased(p, ctxt);
}
// 25-Jan-2017, tatu: We do not actually support use of Creators for non-static
// inner classes -- with one and only one exception; that of default constructor!
// -- so let's indicate it
Class<?> raw = _beanType.getRawClass();
if (ClassUtil.isNonStaticInnerClass(raw)) {
return ctxt.handleMissingInstantiator(raw, null, p,
"non-static inner classes like this can only by instantiated using default, no-argument constructor");
}
return ctxt.handleMissingInstantiator(raw, getValueInstantiator(), p,
"cannot deserialize from Object value (no delegate- or property-based Creator)");
}
deserializeFromObjectUsingNonDefault
๋ฉ์๋๋ช
์ ์ดํด๋ณด๋ฉด ๊ธฐ๋ณธ์์ฑ์ ์์ด ์ญ์ง๋ ฌํํ๋ ๋ฉ์๋์
๋๋ค.
์ด ๋ฉ์๋๊ฐ ํ๋ค๋ฉด ๋ฐ๋ก ์๋ฌ๋ฅผ ์ฐ์ด์ผํ๋๋ฐ ์ธ๋ถ ๋ก์ง์ ๋ณด๋ฉด
final JsonDeserializer<Object> delegateDeser = _delegateDeserializer();
if (delegateDeser != null) {
final Object bean = _valueInstantiator.createUsingDelegate(ctxt,
delegateDeser.deserialize(p, ctxt));
if (_injectables != null) {
injectValues(ctxt, bean);
}
return bean;
}
delegateDeser != null
delegate๊ฐ ์กด์ฌํ๋ค๋ฉด createUsingDelegate
๋ฉ์๋๋ฅผ ํตํด ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๋ก์ง์ด ๋ค์ด๊ฐ ์์ต๋๋ค.
์ง๊ธ ์ ์ ์ํฉ์ delegateDeser == null
์ด๊ธฐ ๋๋ฌธ์ ๋ง์ง๋ง ๊ตฌ๋ฌธ์ ์๋ฌ๋ก๊ทธ๊ฐ ์ถ๋ ฅ๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
๋ํ ๊ทธ ๋ฐ์ ๋ก์ง์ธ
if (_propertyBasedCreator != null) {
return _deserializeUsingPropertyBased(p, ctxt);
}
_propertyBasedCreator
๋ ์๋๊ธฐ ๋๋ฌธ์ ์ ๋ฐ ์๋ฌ๊ฐ ์ฐํ๊ฒ์
๋๋ค.
์ ๋ฆฌ
๊ฒฐ๊ตญ, ์ ์ ๋ฌธ์ ๋ Controller์์ API ์์ฒญ ์คํ์ ์ ๋ฌํ๋ DTO์ ๊ฐ์ฒด๋ก์จ ๊ธฐ๋ณธ์์ฑ์๊ฐ ์์๊ธฐ์ ๋ํ๋ ๋ฌธ์ ์์ต๋๋ค.
๊ฐ๋จํ ๊ธฐ๋ณธ์์ฑ์๋ฅผ ์ถ๊ฐํด์ ์๋ฌ๋ฅผ ํด๊ฒฐํ ์ ์์์ต๋๋ค.
๋กฌ๋ณต์ @builder๋ ๊ธฐ๋ณธ์์ฑ์๋ฅผ ์์ฑํด์ฃผ์ง ์๊ธฐ์ ์ด๋ฐ ์ํฉ์ด ๋ฐ์ํ์์ต๋๋ค.. ๐ฑ
์ฐ๋ฆฌ ๋ชจ๋ ํ๋๋ง ๊ธฐ์ตํฉ์๋ค.
์ญ์จ์ object mapper๋ ๊ธฐ๋ณธ์์ฑ์๋ฅผ ํ์๋กํ๋ค! (๊ธฐ๋ณธ์์ฑ์๋ private
์ด์ด๋ ๋๋ค! ๋ฆฌํ๋ ์
)
๋ฒ์ธ๋ก @JsonProperty
, @JsonAutoDetect
๋ฑ์ ์ฌ์ฉํ๋ ํ๋กํผํฐ ๊ธฐ๋ฐ ๊ฐ์ฒด or ์์ฑ์๋ฅผ ์์ํ ๊ฒฝ์ฐ๋ผ๋ฉด ํ์ํ์ง ์๋ค!
๋.
Uploaded by N2T