@JsonTypeInfo 可以与集合一起使用吗?

发布于 2024-12-05 03:35:22 字数 678 浏览 2 评论 0原文

使用 Spring 3 和 Jackson 1.7.6,我可以序列化抽象类的实现,并将该类的完全限定名称输出为名为 @class 的属性。当我的 Spring 控制器从用 @ResponseBody 注释的控制器返回单个实例时,这可以正常工作。

当返回上述类型的 Collection 时,生成的 JSON 根据序列化的类型(存在每个子类的字段)而变化,但它不包括 @class属性,这是我们的客户端代码需要的。

返回集合时,如何将此类型提示放入序列化 JSON 中?

//Returns complete with @class=com.package.blah
@RequestMapping("/json/getProduct.json")
public @ResponseBody Product getProduct(Integer id)
{
    return service.getProduct(id);
}

//Does not include @class 
@RequestMapping("/json/getProducts.json")
public @ResponseBody List<Product> getProducts()
{
    return service.getProducts();
}

Using Spring 3 and Jackson 1.7.6, I can serialize implementations of an abstract class and output the fully-qualified name of the class as a property called @class. This works fine when my Spring controllers return a single instance from a controller annotated with @ResponseBody.

When returning a Collection of the above types the resulting JSON changes according to which type is being serialized (fields from each subclass are present), but it does not include the @class property, which our client code needs.

How can I get this type hint into the serialized JSON when returning a collection?

//Returns complete with @class=com.package.blah
@RequestMapping("/json/getProduct.json")
public @ResponseBody Product getProduct(Integer id)
{
    return service.getProduct(id);
}

//Does not include @class 
@RequestMapping("/json/getProducts.json")
public @ResponseBody List<Product> getProducts()
{
    return service.getProducts();
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

清风无影 2024-12-12 03:35:22

为此,您需要配置 ObjectMapper。通过 Spring 这并不简单,因为 ObjectMapper 不是可设置的属性,而是具有设置其状态的可调用方法(然后将其存储为位掩码)。

如果您使用 ,您需要将其替换为等效的标记,可以在 Spring JavaDocs 中找到该标记。

扩展ObjectMapper:

public class ConfigurableObjectMapper extends ObjectMapper
{
    public ConfigurableObjectMapper()
    {
        this.enableDefaultTypingAsProperty(DefaultTyping.JAVA_LANG_OBJECT, JsonTypeInfo.Id.CLASS.getDefaultPropertyName());
    }
}

然后告诉Spring使用此类的实例而不是默认实现。

<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
    <property name="order" value="0" />
</bean>

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="webBindingInitializer">
        <bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
            <property name="validator" ref="validator" />
        </bean>
    </property>
    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
                <property name="objectMapper">
                    <bean class="com.blitzgamesstudios.web.common.json.ConfigurableObjectMapper" />
                </property>
            </bean>
            <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
            <bean class="org.springframework.http.converter.StringHttpMessageConverter" />
            <bean class="org.springframework.http.converter.FormHttpMessageConverter" />
            <bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter" />
        </list>
    </property>
</bean>

<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />

In order to do this you will need to configure ObjectMapper. This is not straightforward via Spring, as rather than settable properties, ObjectMapper has invokable methods that set its state (and then it stores this as a bitmask).

If you are using <mvc:annotation-driven /> you will need to replace it with the equivalent markup, which can be found in the Spring JavaDocs.

Extend ObjectMapper:

public class ConfigurableObjectMapper extends ObjectMapper
{
    public ConfigurableObjectMapper()
    {
        this.enableDefaultTypingAsProperty(DefaultTyping.JAVA_LANG_OBJECT, JsonTypeInfo.Id.CLASS.getDefaultPropertyName());
    }
}

Then tell Spring to use an instance of this class instead of the default implementation.

<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
    <property name="order" value="0" />
</bean>

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="webBindingInitializer">
        <bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
            <property name="validator" ref="validator" />
        </bean>
    </property>
    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
                <property name="objectMapper">
                    <bean class="com.blitzgamesstudios.web.common.json.ConfigurableObjectMapper" />
                </property>
            </bean>
            <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
            <bean class="org.springframework.http.converter.StringHttpMessageConverter" />
            <bean class="org.springframework.http.converter.FormHttpMessageConverter" />
            <bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter" />
        </list>
    </property>
</bean>

<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
木槿暧夏七纪年 2024-12-12 03:35:22

您可以将 @JsonTypeInfo 与 POJO、集合和映射一起使用,但请注意,集合和映射的声明值类型必须是具有(或继承)@JsonTypeInfo 注释的类型(当使用每类 @JsonTypeInfo 注释时)。例如,如果您有“Collection”之类的类型,则这将不起作用 - 在这种情况下,Deejay 的答案是正确的,因为您可以强制包含“默认类型”选项。

但是,如果您有一个要序列化/反序列化的 Collection 属性,那么事情也应该有效,即:

public class Bean {
    @JsonTypeInfo(....)
    public Collection<Object> listOfObjects; // does work because it's per-property annotation!
    // ... also, applies to value type and not Collection type itself
}

因为这将覆盖任何 @JsonTypeInfo 注释值类型,否则可能会具有

You can use @JsonTypeInfo with POJOs, Collections and Maps, but note that the declared value type of Collections and Maps must be one that has (or inherits) @JsonTypeInfo annotation (when using per-class @JsonTypeInfo annotation). This would not work, for example, if you have type like "Collection" -- in this case, Deejay's answer is correct, as you can force inclusion with "default typing" option.

But things should also work if you have a Collection property to serialize/deserialize, i.e.:

public class Bean {
    @JsonTypeInfo(....)
    public Collection<Object> listOfObjects; // does work because it's per-property annotation!
    // ... also, applies to value type and not Collection type itself
}

since that will override any @JsonTypeInfo annotations value type might otherwise have

红尘作伴 2024-12-12 03:35:22

我遇到了 java.util.Map 的问题,所以我做了类似的事情:

public interface MyMap extends Map; {}

public class MyHashMap extends HashMap;实现 MyMap {}

发现于:http://jackson-users.ning.com/forum/topics/mapper-not-include-type-in​​formation-when-serializing-object-why

I had the problem withjava.util.Map, so I did something like:

public interface MyMap extends Map<Long, Product> {}

and

public class MyHashMap extends HashMap<Long, Product> implements MyMap {}

Found on: http://jackson-users.ning.com/forum/topics/mapper-not-include-type-information-when-serializing-object-why

玻璃人 2024-12-12 03:35:22

对象映射器 bean 可以启用默认类型:

ObjectMapper mapper = new ObjectMapper()
mapper.enableDefaultTyping(DefaultTyping.NON_FINAL, As.PROPERTY);

这将给出 json 输出,如下所示:

[
    "java.util.ArrayList",
    [
        {
            "@class": "com.xyz.Product",
            "name": "myName"
        }
     ]
]

Object mapper bean can enable default typing:

ObjectMapper mapper = new ObjectMapper()
mapper.enableDefaultTyping(DefaultTyping.NON_FINAL, As.PROPERTY);

This will give the json output as following:

[
    "java.util.ArrayList",
    [
        {
            "@class": "com.xyz.Product",
            "name": "myName"
        }
     ]
]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文