[SPRING] 잭슨을 사용하여 자바에 POJO로 JSON 변환하는 방법
SPRING잭슨을 사용하여 자바에 POJO로 JSON 변환하는 방법
나는 봄 3.1.2를 사용하고 있는데 나는 POJO로 JSON 개체를 구문 분석 할 필요가있다. 이것은 내가 구문 분석하는 데 필요한 JSON입니다 :
{
"Person" : {
"id" : "2"
},
"Dog" : {
"dateOfBirth" : "2012-08-20 00:00:00",
"price" : "10.00"
}
}
내가 한 POJO로 (두 객체에서 결합)이 JSON 객체로 변환 할 필요가 여기있다 :
public class MyClass{
public MyClass(){}
public MyClass(String personsId, TimeStamp dogsDateOfBirth, BigDecimal dogsPrice){
.... // assign each parameter to the appropriate field
}
private String personsId;
private TimeStamp dogsDateOfBirth;
private BigDecimal dogsPrice;
//... Getters and Setters for each field
}
그 문제에 내가 ObjectMapper 매퍼 = 새로운 ObjectMapper를 사용 (); 이제이 있기 때문에 여러 JSON 내 코드는 다음과 같습니다 객체 :
String json = ... ;// A json with several objects as above
JsonNode tree = mapper.readTree(json);
Iterator<JsonNode> iter = tree.path("data").getElements();
while (iter.hasNext()){
JsonNode node = iter.next();
MyClass myClass = mapper.readValue(node, MyClass.class);
... // do something with myClass object
}
나는이 프로그램을 실행할 때 - 나는 다음과 같은 예외를 얻을 :
org.codehaus.jackson.map.JsonMappingException: No suitable constructor found for type [simple type, class ...MyClass]: can not instantiate from JSON object (need to add/enable type information?)
나는 간단한 POJO를 만들려고 - 사람을 :
public class Person{
private String id;
public Person(){}
public Person(String id){
this.id = id;
}
... // Getter and Setter
}
다음을 수행 :
Person person = mapper.readValue(node.path("Person"), Person.class);
나는이 (같은) 예외를 얻을 :
org.codehaus.jackson.map.JsonMappingException: No suitable constructor found for type [simple type, class ...Person]: can not instantiate from JSON object (need to add/enable type information?)
나는 형식 정보에 대한 몇 가지를 읽으려고 -하지만 여기에 나를 도울 수있는 방법을 이해할 수 없었다.
어떻게 POJO에이 JSON을 변환 할 수 있습니까?
감사.
해결법
-
==============================
1.내가 한 일은이 있었다 : 나는 Person 객체와 개 개체를 보유 새로운 클래스, 이러한 클래스는 (내가 여기 있음) 고정 할 필요가 만들었습니다. 여기에 클래스는 다음과 같습니다
내가 한 일은이 있었다 : 나는 Person 객체와 개 개체를 보유 새로운 클래스, 이러한 클래스는 (내가 여기 있음) 고정 할 필요가 만들었습니다. 여기에 클래스는 다음과 같습니다
public static class MyNewClass{ private Person person; private Dog dog; ... // two constructors and getters and setters public static class Person{ private String id; ... // two constructors and getters and setters } public static class Dog{ private String dateOfBirth; private String price; ... // two constructors and getters and setters } }
이제 내 코드는 다음과 같습니다 :
JsonNode tree = mapper.readTree(jsonString); Iterator<JsonNode> iter = tree.path("data").getElements(); while (iter.hasNext()){ JsonNode node = iter.next(); Person person = mapper.readValue(node.path("Person"), Person.class); Dog dog = mapper.readValue(node.path("Dog"), Dog.class); MyNewClass myNewClass = new MyNewClass(person , dog); ... //Do something with it }
지금은 충분히 That'a 좋은 - - 나는 아직도이 두 개체 (사람과 개를) 만들지 않고 그것을 할 싶어하지만 누군가가 생각이있는 경우 - 여기 싶습니다!
감사.
-
==============================
2.잭슨 오류 : 문제는 여기에 설명과 동일하지 않습니다 더 적합한 생성자
잭슨 오류 : 문제는 여기에 설명과 동일하지 않습니다 더 적합한 생성자
인스턴스화하려는 클래스는 정적 없습니다. 그 때문에, 그것은 숨겨진 생성자의 매개 변수가 있습니다. 이는 잭슨이 실패하는 원인이된다.
-
==============================
3.모든 필드가 JSON 데이터를 문자열이기 때문에, 모든 필드에 대한 문자열을 받아 MyClass의 생성자를 변경해보십시오. BTW, 거기에 JSON 타임 스탬프에 대한 표준 표현은 없다, 그래서 당신은 어쨌든 날짜 필드에 대한 변환을 수행해야합니다. 은 "가격"필드의 경우, 변경을 시도 할 수
모든 필드가 JSON 데이터를 문자열이기 때문에, 모든 필드에 대한 문자열을 받아 MyClass의 생성자를 변경해보십시오. BTW, 거기에 JSON 타임 스탬프에 대한 표준 표현은 없다, 그래서 당신은 어쨌든 날짜 필드에 대한 변환을 수행해야합니다. 은 "가격"필드의 경우, 변경을 시도 할 수
"price" : "10.00"
에
"price" : 10.00
JSON 데이터 단계; 즉,이 BigDecimal를로 읽을 수 있도록해야한다.
-
==============================
4.당신은 하나의 자바 객체로 두 JSON 객체를 결합하려는 경우 여기 Genson 라이브러리 http://code.google.com/p/genson/있는 솔루션입니다. 다음 코드 단축 및 사용 Gensons 표준 컨버터하지만 그것은 예를 들어 덜 명확 것입니다 수 있습니다. 여기 장점은 매우 빠르고, 그래서 당신이 직접 스트리밍 API를 사용하고 있다는 점이다.
당신은 하나의 자바 객체로 두 JSON 객체를 결합하려는 경우 여기 Genson 라이브러리 http://code.google.com/p/genson/있는 솔루션입니다. 다음 코드 단축 및 사용 Gensons 표준 컨버터하지만 그것은 예를 들어 덜 명확 것입니다 수 있습니다. 여기 장점은 매우 빠르고, 그래서 당신이 직접 스트리밍 API를 사용하고 있다는 점이다.
class MyClassConverter implements Deserializer<MyClass> { @Override public MyClass deserialize(ObjectReader reader, Context ctx) throws TransformationException, IOException { reader.beginObject(); MyClass myClass = new MyClass(); for (; reader.hasNext();) { reader.next(); if ("Person".equals(reader.name())) { readPerson(reader, myClass); } else if ("Dog".equals(reader.name())) { readDog(reader, myClass); } } reader.endObject(); return myClass; } private void readPerson(ObjectReader reader, MyClass myClass) throws IOException { reader.beginObject(); for (; reader.hasNext();) { reader.next(); if ("id".equals(reader.name())) myClass.setPersonsId(reader.valueAsString()); } reader.endObject(); } private void readDog(ObjectReader reader, MyClass myClass) throws IOException { reader.beginObject(); for (; reader.hasNext();) { reader.next(); if ("dateOfBirth".equals(reader.name())) myClass.setDogsDateOfBirth(Timestamp.valueOf(reader.valueAsString())); else if ("price".equals(reader.name())) myClass.setDogsPrice(new BigDecimal(reader.valueAsString())); } reader.endObject(); } }
당신은 당신이 분리 된 개체로 사람과 개를 가지고 다른 예를 원하는 경우에 당신은 Gensons 사용자 그룹에 요청할 수 있습니다.
도움이 되었기를 바랍니다!
편집하다 여기에 또 다른 버전 짧고 좋네요하지만 (나는 저자로 아마 오늘 새 버전을 출시 할 예정 :)) 릴리스 버전 0.91에 포함되지 않습니다 당신이 (당신은 또한 직렬화를 할 경우와 setter) @JsonProperty (the_name_from_json)와 게터에 주석을해야합니다 작동하게합니다. 당신이 필드 만 사용하려는 경우 Genson 어떤 게터 / 세터가 필요하지 않습니다 (그렇지 않으면 필드 avaible 경우 기본적으로는 게터 / 세터를 사용한다).
Genson genson = new Genson.Builder().withDeserializerFactory(new MyClassConverterFactory()).create(); MyClass myClass = genson.deserialize(json, MyClass.class); public static class MyClassConverterFactory implements Factory<Deserializer<MyClass>> { @SuppressWarnings("unchecked") @Override public Deserializer<MyClass> create(Type type, Genson genson) { BeanDescriptor<MyClass> myClassDescriptor = (BeanDescriptor<MyClass>) genson.getBeanDescriptorFactory().provide(MyClass.class, genson); return new MyClassConverter(myClassDescriptor); } } public static class MyClassConverter implements Deserializer<MyClass> { BeanDescriptor<MyClass> myClassDescriptor; public MyClassConverter(BeanDescriptor<MyClass> myClassDescriptor) { this.myClassDescriptor = myClassDescriptor; } @Override public MyClass deserialize(ObjectReader reader, Context ctx) throws TransformationException, IOException { reader.beginObject(); MyClass myClass = new MyClass(); for (; reader.hasNext();) { reader.next(); if ("Person".equals(reader.name())) { myClassDescriptor.deserialize(myClass, reader, ctx); } else if ("Dog".equals(reader.name())) { myClassDescriptor.deserialize(myClass, reader, ctx); } } reader.endObject(); return myClass; } }
-
==============================
5.참고 : 나는 EclipseLink가 JAXB (목시) 리드와 JAXB (JSR-222) 전문가 그룹의 구성원입니다.
참고 : 나는 EclipseLink가 JAXB (목시) 리드와 JAXB (JSR-222) 전문가 그룹의 구성원입니다.
당신은 당신의 유스 케이스를 지원하기 위해 목시에 경로 기반의 매핑을 활용할 수 있습니다.
내 수업
@XmlPath 주석은 경로 기반 매핑을 지정하는 데 사용됩니다 :
package forum12139380; import java.math.BigDecimal; import java.sql.Timestamp; import org.eclipse.persistence.oxm.annotations.XmlPath; import javax.xml.bind.annotation.*; @XmlAccessorType(XmlAccessType.FIELD) public class MyClass { public MyClass() { } public MyClass(String personsId, Timestamp dogsDateOfBirth, BigDecimal dogsPrice) { this.personsId = personsId; this.dogsDateOfBirth = dogsDateOfBirth; this.dogsPrice = dogsPrice; } @XmlPath("Person/id/text()") private String personsId; @XmlPath("Dog/dateOfBirth/text()") private Timestamp dogsDateOfBirth; @XmlPath("Dog/price/text()") @XmlSchemaType(name="string") private BigDecimal dogsPrice; // ... Getters and Setters for each field }
jaxb.properties
다음 항목으로 도메인 모델과 동일한 패키지에 jaxb.properties라는 파일을 포함 할 필요가 당신의 JAXB 공급자로 MOXY를 지정하려면 :
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
데모
아래의 코드는 JSON의 뒤쪽으로 객체에 JSON 변환 한 것입니다.
package forum12139380; import java.util.*; import javax.xml.bind.*; import javax.xml.transform.stream.StreamSource; import org.eclipse.persistence.jaxb.JAXBContextProperties; public class Demo { public static void main(String[] args) throws Exception { Map<String, Object> properties = new HashMap<String, Object>(2); properties.put(JAXBContextProperties.MEDIA_TYPE, "application/json"); properties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false); JAXBContext jc = JAXBContext.newInstance(new Class[] {MyClass.class}, properties); Unmarshaller unmarshaller = jc.createUnmarshaller(); StreamSource json = new StreamSource("src/forum12139380/input.json"); MyClass myClass = (MyClass) unmarshaller.unmarshal(json, MyClass.class).getValue(); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(myClass, System.out); } }
input.xml / 출력
아래는 데모 코드를 실행에서 입력 및 출력이다. 내 예제에서 나는 타임 스탬프의 목시의 기본 reprentation을 사용하고 있습니다. 당신은 (: JAXB 비 정렬 화 타임 스탬프를 참조) (때문에) XmlAdapter로 쉽게 표현을 제어 할 수 있습니다.
{ "Person" : { "id" : "2" }, "Dog" : { "dateOfBirth" : "2012-08-20T00:00:00.0", "price" : "10.00" } }
-
==============================
6.이 모든 답은 POJO를 사용하여 그것을 할 수있는 유일한 방법임을 의미한다. 물론, 웹 프로젝트, 봄 웹 서비스 프로젝트처럼, POJO의를하는 것이 중요하지만, 단지 단위 테스트를 위해 당신은 단지 일반적인 잭슨 JsonNode 개체를 사용할 수 있을까?
이 모든 답은 POJO를 사용하여 그것을 할 수있는 유일한 방법임을 의미한다. 물론, 웹 프로젝트, 봄 웹 서비스 프로젝트처럼, POJO의를하는 것이 중요하지만, 단지 단위 테스트를 위해 당신은 단지 일반적인 잭슨 JsonNode 개체를 사용할 수 있을까?
당신은 단순히 수없는 POJO 클래스를 사용하지 않고 잭슨 ObjectMapper를 사용하여 JsonNode으로 해제 직렬화? JsonNode의 인스턴스는 그 자체로는 법적 잭슨 POJO로 인정하지 않습니다? 난 당신이 JsonNode 인스턴스를 일단 당신이 JSON 개체를 얻을 수 없기 때문에 확신 같은 :
node.get(0).get(1).get("nodename").asText();
from https://stackoverflow.com/questions/12139380/how-to-convert-json-into-pojo-in-java-using-jackson by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] 조건 검색 필터를 구현 (0) | 2019.10.04 |
---|---|
[SPRING] CrudRepository에서 사용자 지정 SQL 쿼리 (0) | 2019.10.04 |
[SPRING] 봄 사양 및 Pageable를 (0) | 2019.10.04 |
[SPRING] 어떻게 잭슨 objectmapper에 dateformat 설정 봄에 MVC 설정을 추가하는 방법은 무엇입니까? (0) | 2019.10.04 |
[SPRING] 내 스프링 JPA 통합 테스트를 위해 일을 @Rollback를 가져올 수 없습니다 (0) | 2019.10.04 |