Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在没有JAXBElement包装器的情况下使用JSON封送JAXBElement包装的响应?_Java_Json_Spring_Jackson_Jaxbelement - Fatal编程技术网

Java 如何在没有JAXBElement包装器的情况下使用JSON封送JAXBElement包装的响应?

Java 如何在没有JAXBElement包装器的情况下使用JSON封送JAXBElement包装的响应?,java,json,spring,jackson,jaxbelement,Java,Json,Spring,Jackson,Jaxbelement,我有一个http服务正在使用Spring(v4.0.5)。它的http端点是使用SpringWebMVC配置的。响应是根据模式生成的JAXB2类。响应被包装在JAXBElement中,因为生成的JAXB类不包含@XmlRootElement注释(并且不能修改模式以实现此目的)。我不得不接受XML编组的工作;无论如何,它是有效的 现在我正在设置JSON编组。我遇到的是获取具有JAXBElement“信封”特性的JSON文档 我想要封送的只是值-对象: { "what": "what", "

我有一个http服务正在使用Spring(v4.0.5)。它的http端点是使用SpringWebMVC配置的。响应是根据模式生成的JAXB2类。响应被包装在
JAXBElement
中,因为生成的JAXB类不包含
@XmlRootElement
注释(并且不能修改模式以实现此目的)。我不得不接受XML编组的工作;无论如何,它是有效的

现在我正在设置JSON编组。我遇到的是获取具有
JAXBElement
“信封”特性的JSON文档

我想要封送的只是
-对象:

{
  "what": "what",
  "when": "2014-06-09T15:56:46Z"
}
以下是我的JSON编组配置(spring上下文配置的一部分):


我希望这可以通过配置
ObjectMapper
来实现。我想,或者推出我自己的序列化程序可能会奏效。思想?建议?

您可以为JAXBElement类注册一个注释,该注释将放在JAXBElement.getValue()方法上,使其返回值成为JSON表示。以下是一个例子:

示例.xsd chema文件提供给
xjc

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="item" type="Thing"/>

    <xs:complexType name="Thing">
        <xs:sequence>
            <xs:element name="number" type="xs:long"/>
            <xs:element name="string" type="xs:string" minOccurs="0"/>
        </xs:sequence>
    </xs:complexType>

</xs:schema>

Java主类:

public class JacksonJAXBElement {
    // a mixin annotation that overrides the handling for the JAXBElement
    public static interface JAXBElementMixin {
        @JsonValue
        Object getValue();
    }

    public static void main(String[] args) throws JAXBException, JsonProcessingException {
        ObjectFactory factory = new ObjectFactory();
        Thing thing = factory.createThing();
        thing.setString("value");
        thing.setNumber(123);
        JAXBElement<Thing> orderJAXBElement = factory.createItem(thing);

        System.out.println("XML:");
        JAXBContext jc = JAXBContext.newInstance(Thing.class);
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        marshaller.marshal(orderJAXBElement, System.out);
        System.out.println("JSON:");

        ObjectMapper mapper = new ObjectMapper();
        mapper.addMixInAnnotations(JAXBElement.class, JAXBElementMixin.class);
        System.out.println(mapper.writerWithDefaultPrettyPrinter()
                .writeValueAsString(orderJAXBElement));
    }
}
公共类JacksonJAXBElement{
//覆盖JAXBElement处理的mixin注释
公共静态接口JAXBElementMixin{
@JsonValue
对象getValue();
}
公共静态void main(字符串[]args)抛出JAXBEException、JsonProcessingException{
ObjectFactory=新的ObjectFactory();
Thing=factory.createThing();
设置字符串(“值”);
设置编号(123);
JAXBElement orderJAXBElement=factory.createItem(thing);
System.out.println(“XML:”);
JAXBContext jc=JAXBContext.newInstance(Thing.class);
Marshaller=jc.createMarshaller();
setProperty(marshaller.JAXB_格式的_输出,Boolean.TRUE);
marshaller.marshall(orderJAXBElement,System.out);
System.out.println(“JSON:”);
ObjectMapper mapper=新的ObjectMapper();
addMixinNotations(JAXBElement.class、JAXBElementMixin.class);
System.out.println(mapper.writerWithDefaultPrettyPrinter()
.writeValueAsString(orderJAXBElement));
}
}
输出:

XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<item>
    <number>123</number>
    <string>value</string>
</item>
JSON:
{
  "number" : 123,
  "string" : "value"
}
XML:
123
价值
JSON:
{
“数字”:123,
“字符串”:“值”
}

有关完整配置项目的示例,请参见:

  • 仅使用Spring(v4.0.5)进行内容协商和封送处理
  • 使用JAXB生成响应的对象表示
  • 支持XML和JSON内容协商
  • 在封送JSON响应时尊重JAXB注释
  • 避免在响应对象周围泄漏
    JAXBElement
    -wrapper
头朝上

重要的部分是:

  • Jackson mixin,允许Jackson在封送前从
    JAXBElement
    -包装中打开响应对象
  • Spring上下文配置,它将JSON对象映射器配置为使用Jackson,并将所述映射器配置为利用mixin并使用
    注释IntrospectorPair
    (注意,页面有点过时),该配置将JAXB注释内省器配置为主内省器(确保响应符合XSD的规定)并将Jackson响应作为次要响应(确保
    JAXBElement
    unwrapping mixin发挥作用)
混音

/**
 * Ensures, when the Jackson {@link ObjectMapper} is configured with it, that
 * {@link JAXBElement}-wrapped response objects when serialized as JSON documents
 * do not feature the JAXBElement properties; but instead the JSON-document that
 * results in marshalling the member returned by the {@link JAXBElement#getValue()}
 * call.
 * <p>
 * More on the usage and configuration options is available
 * <a href="http://wiki.fasterxml.com/JacksonMixInAnnotations">here</a>.
 */
public interface JaxbElementMixin {
  @JsonValue
  Object getValue();
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:aop="http://www.springframework.org/schema/aop"
  xmlns:context="http://www.springframework.org/schema/context" 
  xmlns:tx="http://www.springframework.org/schema/tx"
  xmlns:util="http://www.springframework.org/schema/util" 
  xmlns:mvc="http://www.springframework.org/schema/mvc"
  xmlns:oxm="http://www.springframework.org/schema/oxm"
  xsi:schemaLocation="
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
  http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
  http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
  http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd
  http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
  http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-4.0.xsd">

  <context:component-scan base-package="io.github.gv0tch0.sotaro"/>

  <bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
    <property name="favorPathExtension" value="false" />
    <property name="ignoreAcceptHeader" value="false" />
    <property name="useJaf" value="false" />
    <property name="defaultContentType" value="application/xml" />
    <property name="mediaTypes">
      <map>
        <entry key="xml" value="application/xml" />
        <entry key="json" value="application/json" />
      </map>
    </property>
  </bean>

  <bean id="typeFactory" class="com.fasterxml.jackson.databind.type.TypeFactory" factory-method="defaultInstance" />

  <bean id="jaxbIntrospector" class="com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector">
    <constructor-arg ref="typeFactory" />
  </bean>

  <bean id="jacksonIntrospector" class="com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector" />

  <bean id="annotationIntrospector" class="com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair">
    <!-- Note that in order to get the best of both the JAXB annotation instrospector and the Mixin configuration
         the JAXB introspector needs to be the primary introspector, hence it needs to stay at position 0. -->
    <constructor-arg index="0" ref="jaxbIntrospector" />
    <constructor-arg index="1" ref="jacksonIntrospector" />
  </bean>

  <bean id="jacksonMapper" class="com.fasterxml.jackson.databind.ObjectMapper">
    <property name="annotationIntrospector" ref="annotationIntrospector" />
    <!-- The mixin ensures that when JAXBElement wrapped responses are marshalled as JSON the
         JAXBElement "envelope" gets discarded (which makes our JSON responses conform to spec). -->
    <property name="mixInAnnotations">
      <map key-type="java.lang.Class" value-type="java.lang.Class">
        <entry key="javax.xml.bind.JAXBElement" value="io.github.gv0tch0.sotaro.JaxbElementMixin" />
      </map>
    </property>
    <property name="dateFormat">
      <bean class="java.text.SimpleDateFormat">
        <constructor-arg type="java.lang.String" value="yyyy-MM-dd'T'HH:mm:ss'Z'" />
        <property name="timeZone">
          <bean class="java.util.TimeZone" factory-method="getTimeZone">
            <constructor-arg type="java.lang.String" value="UTC" />
          </bean>
        </property>
      </bean>
    </property>
  </bean>

  <bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
    <property name="objectMapper" ref="jacksonMapper" />
    <property name="supportedMediaTypes" value="application/json" />
  </bean>

  <bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
    <property name="supportJaxbElementClass" value="true" />
    <property name="contextPath" value="io.github.gv0tch0.sotaro" />
  </bean>

  <bean id="xmlConverter" class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
    <constructor-arg ref="jaxbMarshaller" />
    <property name="supportedMediaTypes" value="application/xml" />
  </bean>

  <mvc:annotation-driven content-negotiation-manager="contentNegotiationManager">
    <mvc:message-converters register-defaults="false">
      <ref bean="xmlConverter" />
      <ref bean="jsonConverter" />
    </mvc:message-converters>
  </mvc:annotation-driven>

</beans>
/**
*确保在配置Jackson{@link ObjectMapper}时
*{@link JAXBElement}-序列化为JSON文档时包装的响应对象
*不要使用JAXBElement属性,而是使用
*结果是编组{@link JAXBElement#getValue()}返回的成员
*打电话。
*
*有关用法和配置选项的更多信息,请参阅
* .
*/
公共接口JaxbElementMixin{
@JsonValue
对象getValue();
}
Spring上下文配置

/**
 * Ensures, when the Jackson {@link ObjectMapper} is configured with it, that
 * {@link JAXBElement}-wrapped response objects when serialized as JSON documents
 * do not feature the JAXBElement properties; but instead the JSON-document that
 * results in marshalling the member returned by the {@link JAXBElement#getValue()}
 * call.
 * <p>
 * More on the usage and configuration options is available
 * <a href="http://wiki.fasterxml.com/JacksonMixInAnnotations">here</a>.
 */
public interface JaxbElementMixin {
  @JsonValue
  Object getValue();
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:aop="http://www.springframework.org/schema/aop"
  xmlns:context="http://www.springframework.org/schema/context" 
  xmlns:tx="http://www.springframework.org/schema/tx"
  xmlns:util="http://www.springframework.org/schema/util" 
  xmlns:mvc="http://www.springframework.org/schema/mvc"
  xmlns:oxm="http://www.springframework.org/schema/oxm"
  xsi:schemaLocation="
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
  http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
  http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
  http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd
  http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
  http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-4.0.xsd">

  <context:component-scan base-package="io.github.gv0tch0.sotaro"/>

  <bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
    <property name="favorPathExtension" value="false" />
    <property name="ignoreAcceptHeader" value="false" />
    <property name="useJaf" value="false" />
    <property name="defaultContentType" value="application/xml" />
    <property name="mediaTypes">
      <map>
        <entry key="xml" value="application/xml" />
        <entry key="json" value="application/json" />
      </map>
    </property>
  </bean>

  <bean id="typeFactory" class="com.fasterxml.jackson.databind.type.TypeFactory" factory-method="defaultInstance" />

  <bean id="jaxbIntrospector" class="com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector">
    <constructor-arg ref="typeFactory" />
  </bean>

  <bean id="jacksonIntrospector" class="com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector" />

  <bean id="annotationIntrospector" class="com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair">
    <!-- Note that in order to get the best of both the JAXB annotation instrospector and the Mixin configuration
         the JAXB introspector needs to be the primary introspector, hence it needs to stay at position 0. -->
    <constructor-arg index="0" ref="jaxbIntrospector" />
    <constructor-arg index="1" ref="jacksonIntrospector" />
  </bean>

  <bean id="jacksonMapper" class="com.fasterxml.jackson.databind.ObjectMapper">
    <property name="annotationIntrospector" ref="annotationIntrospector" />
    <!-- The mixin ensures that when JAXBElement wrapped responses are marshalled as JSON the
         JAXBElement "envelope" gets discarded (which makes our JSON responses conform to spec). -->
    <property name="mixInAnnotations">
      <map key-type="java.lang.Class" value-type="java.lang.Class">
        <entry key="javax.xml.bind.JAXBElement" value="io.github.gv0tch0.sotaro.JaxbElementMixin" />
      </map>
    </property>
    <property name="dateFormat">
      <bean class="java.text.SimpleDateFormat">
        <constructor-arg type="java.lang.String" value="yyyy-MM-dd'T'HH:mm:ss'Z'" />
        <property name="timeZone">
          <bean class="java.util.TimeZone" factory-method="getTimeZone">
            <constructor-arg type="java.lang.String" value="UTC" />
          </bean>
        </property>
      </bean>
    </property>
  </bean>

  <bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
    <property name="objectMapper" ref="jacksonMapper" />
    <property name="supportedMediaTypes" value="application/json" />
  </bean>

  <bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
    <property name="supportJaxbElementClass" value="true" />
    <property name="contextPath" value="io.github.gv0tch0.sotaro" />
  </bean>

  <bean id="xmlConverter" class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
    <constructor-arg ref="jaxbMarshaller" />
    <property name="supportedMediaTypes" value="application/xml" />
  </bean>

  <mvc:annotation-driven content-negotiation-manager="contentNegotiationManager">
    <mvc:message-converters register-defaults="false">
      <ref bean="xmlConverter" />
      <ref bean="jsonConverter" />
    </mvc:message-converters>
  </mvc:annotation-driven>

</beans>


看看被编组的响应对象是由
xjc
(JAXB2绑定编译器)根据模式生成的。你是否建议以某种方式对它们进行注释?即使以某种方式实现了这一点,它们仍然被包装在
JAXBElement
-s中,它们本身不能被@JsonValue注释…好的。请看我的答案。这在很大程度上是有效的。谢谢!问题是注释中的混合似乎不能很好地混合(没有双关语)事实上,我发现这两个是一个非此即彼的命题。这意味着如果我使用mixin方法从JAXBElement信封中打开实际响应对象进行编组,我必须放弃jaxb注释内省提供的所有功能-例如,属性n的编组ames、enum值等。它们的封送方式与XML中的封送方式相同。也许有人知道如何将两者结合起来。哦,
mixin
-s和
JaxbAnnotationIntrospector
实际上可以。对我来说,将
JaxbAnnotationIntrospector
作为这对函数的主要函数最有效。这种方法可以扩展吗对于二传手也是如此。下面是一个pa