按属性

时间:2015-08-19 13:33:20

标签: java json jackson

我有一个简单的包装类。

class Wrapper {
    int id;
    Object command;
}

command可能是我从外部获取的对象,我无法创建一个接口来将可能的类型保存在一起。 我想简单地序列化它:

String json = objectMapper.writeValueAsString(wrapper);

所以我得到了:

{"id":"1","command":{"type" : "objectType", "key0": "val0", ... other properties...}}

理想情况下,我会使用type的可能值和相应的类名作为值构建一个注册表,因此我可以像这样反序列化它:

Wrapper wrapper = objectMapper.readValue(bytes, Wrapper.class);

objectMappercom.fasterxml.jackson.databind.ObjectMapper

有没有办法通过Jackson来实现这一目标?

2 个答案:

答案 0 :(得分:1)

您可以使用the Jackson polymorphic type handling。您可以使用@JsonTypeXXX注释声明命令属性可以使用哪种类型。

这是一个完整的例子:

public class JacksonTypeInfoOnObject {

    public static class Bean {
        @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
        @JsonSubTypes({
                @JsonSubTypes.Type(Command1.class),
                @JsonSubTypes.Type(Command2.class)
        })
        public final Object command;

        @JsonCreator
        public Bean(@JsonProperty("command") final Object command) {this.command = command;}

        @Override
        public String toString() {
            return "Bean{" +
                    "command=" + command +
                    '}';
        }
    }

    @JsonTypeName("cmd1")
    public static class Command1 {
        @Override
        public String toString() {
            return "Command1{}";
        }
    }

    @JsonTypeName("cmd2")
    public static class Command2 {
        @Override
        public String toString() {
            return "Command2{}";
        }
    }


    public static void main(String[] args) throws IOException {
        final ObjectMapper mapper = new ObjectMapper();
        mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        final List<Bean> list = Arrays.asList(
                new Bean(new Command1()),
                new Bean(new Command2()));
        final String json = mapper.writeValueAsString(list);
        System.out.println(json);
        final List<Bean> values = mapper.readValue(json, new TypeReference<List<Bean>>() {});
        System.out.println(values);
    }
}

输出:

[{"command":{"type":"cmd1"}},{"command":{"type":"cmd2"}}]
[Bean{command=Command1{}}, Bean{command=Command2{}}]

答案 1 :(得分:0)

我将command属性的类型更改为Map<String, Object>,并且可以按预期序列化/反序列化Wrapper对象。

下面是Main类生成的输出:

SERIALIZE:   {"id":1,"command":{"key0":"val0","type":"objectType"}}
DESERIALIZE: Wrapper [id=1, command={key0=val0, type=objectType}]

Main.java

package json;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class Main {
    static ObjectMapper objectMapper = new ObjectMapper();

    private static Wrapper createWrapper() {
        Wrapper wrapper = new Wrapper();
        Map<String, Object> command = new HashMap<String, Object>();

        command.put("type", "objectType");
        command.put("key0", "val0");

        wrapper.id = 1;
        wrapper.command = command;

        return wrapper;
    }

    private static String serializeWrapper(Wrapper wrapperObj) {
        try {
            return objectMapper.writeValueAsString(wrapperObj);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static Wrapper deserializeWrapper(String wrapperJsonStr) {
        try {
            return objectMapper.readValue(wrapperJsonStr, Wrapper.class);
        } catch (JsonParseException e) {
            e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    public static void main(String[] args) {
        Wrapper wrapper = createWrapper();

        String wrapperJsonStr = serializeWrapper(wrapper);
        System.out.printf("SERIALIZE:   %s%n", wrapperJsonStr);

        Wrapper wrapperObj = deserializeWrapper(wrapperJsonStr);
        System.out.printf("DESERIALIZE: %s%n", wrapperObj);
    }
}

Wrapper.java

package json;

import java.util.Map;

public class Wrapper {
    public int id;
    public Map<String, Object> command;

    @Override
    public String toString() {
        return "Wrapper [id=" + id + ", command=" + command + "]";
    }
}