如何使用jackson ObjectMapper将POJO映射到自定义Map?

时间:2016-09-18 08:16:56

标签: java json serialization jackson

我有一个名为ObjectMap的自定义地图实现,如下所示:

public class ObjectMap extends LinkedHashMap<String, Object> implements Serializable {
...
}

我可以使用jackson ObjectMapper将任何POJO转换为此ObjectMap,如下所示:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(
             objectMapper.getSerializationConfig().
             getDefaultVisibilityChecker().
             withFieldVisibility(JsonAutoDetect.Visibility.ANY).
             withGetterVisibility(JsonAutoDetect.Visibility.NONE).
             withIsGetterVisibility(JsonAutoDetect.Visibility.NONE)
);
ObjectMap objectMap = objectMapper.convertValue(object, new TypeReference<ObjectMap>() {});

但问题是如果我的POJO的复杂字段被映射到LinkedHashMap而不是ObjectMap。那么如何强制ObjectMapper将内部字段也映射到ObjectMap而不是LinkedHashMap?

1 个答案:

答案 0 :(得分:1)

我最后提出了以下解决方案:

public class Document extends LinkedHashMap<String, Object> implements Serializable {
}

public class JacksonMapper {
    private ObjectMapper objectMapper;

    public <T> Document asDocument(T object) {
        ObjectMapper objectMapper = getObjectMapper();
        JsonNode node = objectMapper.convertValue(object, JsonNode.class);
        return loadDocument(node);
    }

    protected ObjectMapper getObjectMapper() {
        if (objectMapper == null) {
            objectMapper = new ObjectMapper();
            objectMapper.setVisibility(
                    objectMapper.getSerializationConfig().
                            getDefaultVisibilityChecker().
                            withFieldVisibility(JsonAutoDetect.Visibility.ANY).
                            withGetterVisibility(JsonAutoDetect.Visibility.NONE).
                            withIsGetterVisibility(JsonAutoDetect.Visibility.NONE)
            );
            objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
            objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        }
        return objectMapper;
    }

    private Document loadDocument(JsonNode node) {
        Document document = new Document();
        Iterator<Map.Entry<String, JsonNode>> fields = node.fields();
        while (fields.hasNext()) {
            Map.Entry<String, JsonNode> entry = fields.next();
            String name = entry.getKey();
            JsonNode value = entry.getValue();
            document.put(name, loadObject(value));
        }

        return document;
    }

    private Object loadObject(JsonNode node) {
        if (node == null) return null;
        try {
            switch (node.getNodeType()) {
                case ARRAY:
                    return loadArray(node);
                case BINARY:
                    return node.binaryValue();
                case BOOLEAN:
                    return node.booleanValue();
                case MISSING:
                case NULL:
                    return null;
                case NUMBER:
                    return node.numberValue();
                case OBJECT:
                    return loadDocument(node);
                case POJO:
                    return loadDocument(node);
                case STRING:
                    return node.textValue();
            }
        } catch (IOException e) {
            return null;
        }
        return null;
    }

    private List loadArray(JsonNode array) {
        if (array.isArray()) {
            List list = new ArrayList();
            Iterator iterator = array.elements();
            while (iterator.hasNext()) {
                Object element = iterator.next();
                if (element instanceof JsonNode) {
                    list.add(loadObject((JsonNode) element));
                } else {
                    list.add(element);
                }
            }
            return list;
        }
        return null;
    }
}

希望有一天这会有所帮助。