如何使用Jackson将JSON字段名转换为javabean类属性

如何使用Jackson将JSON字段名转换为javabean类属性,java,json,jackson,Java,Json,Jackson,我可以访问返回JSON字符串的RESTful API,例如: { "Container1": { "active": true }, "Container2": { "active": false }, } 问题是RESTful API设计有点不当。字段名已包含数据。使用Jackson库,无法将字段名反序列化为相应javabean类的属性名。我想,JSON规范也不打算这样做。上述JSON字符串需要反序列化为以下类的实例: 公营货柜

我可以访问返回JSON字符串的RESTful API,例如:

{
    "Container1": {
        "active": true
    },
    "Container2": {
        "active": false
    },
}
问题是RESTful API设计有点不当。字段名已包含数据。使用Jackson库,无法将字段名反序列化为相应javabean类的属性名。我想,JSON规范也不打算这样做。上述JSON字符串需要反序列化为以下类的实例:

公营货柜{ 私有布尔活动; 私有字符串名称; } 最后,字段Container1出现无法识别的属性异常

我想配置为忽略未知属性,并为该属性提供JsonDeserializer,如下所示:

@JsonIgnorePropertiesignoreUnknown=true 公营货柜{ 私有布尔活动; 私有字符串名称; @JsonDeserializeusing=fieldnameTropertyDeserializer.class public void setNameString名称{ this.name=名称; } } 和FieldNameTopPropertyDeserializer:

公共类FieldNameTopPropertySerializer扩展了STDESerializer{ 公共字段名TopPropertySerializer{ 超弦级; } @凌驾 公共字符串反序列化JSONParser解析器,反序列化上下文上下文抛出IOException,JsonProcessingException{ 返回parser.getCurrentName; } } 反序列化的调用如下所示:

String jsonString=response.readEntityString.class; ObjectMapper ObjectMapper=新的ObjectMapper; ObjectReader readerFor=objectMapper.readerForContainer.class; MappingIterator MappingIterator=readerFor.readValuesjsonString; 而mappingIterator.hasNext{ 容器容器=容器映射迭代器.next; containers.addcontainer; } 但我只接收设置为null的空对象属性,因为我将@JsonIgnorePropertiesignoreUnknown=true,因此跳过了对属性的解析


这可能吗?或者我应该在事后实现类似于后处理的功能吗?

这个怎么样。创建一个类ContainerActive,如下所示

public class ContainerActive {
    private  boolean active;
    // constructors, setters, getters
}
你可以这么做

  Map<String, ContainerActive> map = mapper.readValue(jsonString, new TypeReference<Map<String, ContainerActive>>() {});

使用此选项,您将Container1、Container2作为键,ContainerActive对象作为具有活动字段的值

这个怎么样。创建一个类ContainerActive,如下所示

public class ContainerActive {
    private  boolean active;
    // constructors, setters, getters
}
你可以这么做

  Map<String, ContainerActive> map = mapper.readValue(jsonString, new TypeReference<Map<String, ContainerActive>>() {});

使用此选项,您将Container1、Container2作为键,ContainerActive对象作为具有活动字段的值

这只是一个快速的解决方案,如果对象是这样的,那么它的所有对象都是一个容器对象,您可以在其中接收JSON,您可以在下面的代码中使用JSONObject

import java.io.IOException;
import org.json.JSONException;
import org.json.JSONObject;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class TestSO {

    public static void main(String[] args) throws JsonParseException, JsonMappingException, JSONException, IOException {
        String jsonString = "{\r\n" + 
                "    \"Container1\": {\r\n" + 
                "        \"active\": true\r\n" + 
                "    },\r\n" + 
                "    \"Container2\": {\r\n" + 
                "        \"active\": false\r\n" + 
                "    },\r\n" + 
                "}";

        JSONObject jsonObject = new JSONObject(jsonString);

        ObjectMapper mapper = new ObjectMapper();
        for (String key : jsonObject.keySet()) {
            Container container = mapper.readValue(jsonObject.get(key).toString(), Container.class);
            System.out.println(container);
        }   
    }

    static class Container{
        private String name;
        private Boolean active;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public Boolean getActive() {
            return active;
        }
        public void setActive(Boolean active) {
            this.active = active;
        }
        @Override
        public String toString() {
            return "Container [name=" + name + ", active=" + active + "]";
        }
    }
}

这只是一个快速的解决方案,如果对象是这样的,那么它的所有对象都是一个容器对象,您可以在其中接收JSON,并且可以在下面的代码中使用JSONObject

import java.io.IOException;
import org.json.JSONException;
import org.json.JSONObject;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class TestSO {

    public static void main(String[] args) throws JsonParseException, JsonMappingException, JSONException, IOException {
        String jsonString = "{\r\n" + 
                "    \"Container1\": {\r\n" + 
                "        \"active\": true\r\n" + 
                "    },\r\n" + 
                "    \"Container2\": {\r\n" + 
                "        \"active\": false\r\n" + 
                "    },\r\n" + 
                "}";

        JSONObject jsonObject = new JSONObject(jsonString);

        ObjectMapper mapper = new ObjectMapper();
        for (String key : jsonObject.keySet()) {
            Container container = mapper.readValue(jsonObject.get(key).toString(), Container.class);
            System.out.println(container);
        }   
    }

    static class Container{
        private String name;
        private Boolean active;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public Boolean getActive() {
            return active;
        }
        public void setActive(Boolean active) {
            this.active = active;
        }
        @Override
        public String toString() {
            return "Container [name=" + name + ", active=" + active + "]";
        }
    }
}

Jackson–更改字段名称-@ErnstZ是否可能得到更多容器作为响应,例如Container3等?或者后缀是有限的?是的,更多的容器是可能的,它们可以有任何名称。pattern ContainerX只是一个例子。@Dulaj:我不是这个意思。我的问题是我事先不知道字段名。它可能是任何字符串。@ErnstZ Great and ImpressJackson–更改字段名称-@ErnstZ是否可能得到更多容器作为响应,例如Container3等?或者后缀是有限的?是的,更多的容器是可能的,它们可以有任何名称。pattern ContainerX只是一个例子。@Dulaj:我不是这个意思。我的问题是我事先不知道字段名。它可以是任何字符串。@ErnstZ Great和印象派喜欢使用JSONObject,因为字段名和内容在逻辑上是一致的。但您的解决方案不会自动将字段名反序列化为对象的属性。解组容器实例后,需要调用Container.setNamekey。此外,还需要一个依赖项:org.json,但这对我来说没关系。感谢您的贡献。我接受这一贡献作为解决方案,因为它最符合我的期望,因为只有一个添加项需要实现才能获得期望的结果:java container.setNamekey我喜欢使用JSONObject,因为您将字段名和内容逻辑地结合在一起。但您的解决方案不会自动将字段名反序列化为对象的属性。解组容器实例后,需要调用Container.setNamekey。此外,还需要一个依赖项:org.json,但这对我来说没关系。感谢您的贡献。我接受此贡献作为解决方案,因为它最符合我的期望,因为只有一个添加项需要实现才能获得所需的结果:java container.setNamekey是的,这也是将字段名称映射到特定对象的另一种选择。缺点是名称属性
之后必须设置,类似于@Hades.Yes提供的解决方案。你必须这么做。因为您的json实际上并不符合standardYes,所以这也是将字段名映射到特定对象的替代方法。缺点是name属性必须在之后设置,类似于@Hades.Yes提供的解决方案。你必须这么做。因为你的json并不符合标准