如何使用jackson在java中将json转换为POJO

如何使用jackson在java中将json转换为POJO,java,json,spring,jackson,pojo,Java,Json,Spring,Jackson,Pojo,我正在使用Spring3.1.2,需要将json对象解析为POJO。 这是我需要解析的json: { "Person" : { "id" : "2" }, "Dog" : { "dateOfBirth" : "2012-08-20 00:00:00", "price" : "10.00" } } 我需要将这个json对象(由两个对象组合而成)转换为一个POJO,如下所示: public class MyClass{ public MyClass(){

我正在使用Spring3.1.2,需要将json对象解析为POJO。 这是我需要解析的json:

{
"Person" : {
    "id" : "2"
 },
"Dog" : {
    "dateOfBirth" : "2012-08-20 00:00:00",
    "price" : "10.00"
    }
}
我需要将这个json对象(由两个对象组合而成)转换为一个POJO,如下所示:

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 mapper=newobjectmapper()
现在,由于我有几个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
    }
    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
    }
我试图创建一个简单的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 ...MyClass]: can not instantiate from JSON object (need to add/enable type information?)
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?)
我试着读一些关于这方面的书,但不明白这对我有什么帮助

如何将此json转换为POJO


谢谢。

尝试将MyClass的构造函数更改为接受所有字段的
String
,因为所有字段都是JSON数据中的字符串。顺便说一句,JSON中没有时间戳的标准表示形式,因此无论如何都需要对日期字段进行转换。对于“价格”字段,您可以尝试更改

"price" : "10.00"


在JSON数据中;如果您想将两个json对象合并成一个java对象,这里有一个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();
    }
}
类MyClassConverter实现反序列化器{
@凌驾
公共MyClass反序列化(ObjectReader,Context ctx)
抛出TransformationException,IOException{
reader.beginObject();
MyClass MyClass=新的MyClass();
对于(;reader.hasNext();){
reader.next();
if(“Person.equals(reader.name())){
readPerson(reader,myClass);
}else if(“Dog.equals(reader.name())){
readDog(reader,myClass);
}
}
reader.endObject();
返回myClass;
}
私有void readPerson(ObjectReader reader,MyClass MyClass)引发IOException{
reader.beginObject();
对于(;reader.hasNext();){
reader.next();
if(“id”.equals(reader.name()))
myClass.setPersonId(reader.valueAsString());
}
reader.endObject();
}
私有void readDog(ObjectReader阅读器,MyClass MyClass)引发IOException{
reader.beginObject();
对于(;reader.hasNext();){
reader.next();
if(“dateOfBirth.equals(reader.name()))
myClass.setDogsDateOfBirth(Timestamp.valueOf(reader.valueAsString());
else if(“price.equals(reader.name()))
myClass.setDogsPrice(新的BigDecimal(reader.valueAsString());
}
reader.endObject();
}
}
如果您想要其他示例,其中人和狗是分开的对象,您可以询问Gensons用户组

希望这有帮助

编辑 下面是另一个版本,它更短、更好,但没有包含在发布的版本0.91中(我可能会在今天发布新版本,因为我是作者:) 要使其正常工作,您必须使用@JsonProperty(来自于_json的_名称)注释getter(如果您还进行序列化,则为setter)。请注意,如果需要,Genson不需要任何getter/setter,它只能使用字段(默认情况下,如果可用,则使用getter/setter,否则使用字段)

Genson Genson=new Genson.Builder().withDeserializerFactory(new MyClassConverterFactory()).create();
MyClass MyClass=genson.deserialize(json,MyClass.class);
公共静态类MyClassConverterFactory实现工厂{
@抑制警告(“未选中”)
@凌驾
创建公共反序列化程序(类型,Genson-Genson){
BeanDescriptor myClassDescriptor=(BeanDescriptor)genson.getBeanDescriptorFactory().Provider(MyClass.class,genson);
返回新的MyClassConverter(myClassDescriptor);
}
}
公共静态类MyClassConverter实现反序列化器{
BeanDescriptor myClassDescriptor;
公共MyClassConverter(BeanDescriptor myClassDescriptor){
this.myClassDescriptor=myClassDescriptor;
}
@凌驾
公共MyClass反序列化(ObjectReader,Context ctx)
抛出TransformationException,IOException{
reader.beginObject();
MyClass MyClass=新的MyClass();
对于(;reader.hasNext();){
reader.next();
if(“Person.equals(reader.name())){
反序列化(myClass、reader、ctx);
}else if(“Dog.equals(reader.name())){
反序列化(myClass、reader、ctx);
}
}
reader.endObject();
返回myClass;
}
}
我所做的是: 我创建了一个包含Person对象和Dog对象的新类,这些类需要是静态的(我发现了)。 以下是课程:

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
  }
}
现在,我的代码如下所示:

    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
    }
    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
    }
JsonNode tree=mapper.readTree(jsonString);
迭代器iter=tree.path(“数据”).getElements();
while(iter.hasNext()){
JsonNode=iter.next();
Person-Person=mapper.readValue(node.path(“Person”)、Person.class);
Dog Dog=mapper.readValue(node.path(“Dog”)、Dog.class);
MyNewClass MyNewClass=新MyNewClass(人、狗);
…//用它做点什么
}
我仍然想在不创建这两个对象(人和狗)的情况下完成这项工作-这已经足够好了-但是如果有人有想法-我想在这里


谢谢。

注意:我是专家组的负责人和成员

您可以利用MOXy中基于路径的映射来支持您的用例

MyClass

@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

将MOXy指定为JAXB pr
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
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);
    }

}
{
   "Person" : {
      "id" : "2"
   },
   "Dog" : {
      "dateOfBirth" : "2012-08-20T00:00:00.0",
      "price" : "10.00"
   }
}
node.get(0).get(1).get("nodename").asText();