Jackson 使用 dropwizard 生成空的 XML,但不在单元测试中
Jackson producing empty XML with dropwizard but not in unit test
我发现一些用
注释的字段有问题
@JsonSerialize
当周围的 class 从 web-service 作为 XML 返回时,但不在单元测试中。当使用 Accept header of "application/json" 调用服务时,一切正常。当使用 "application/xml" 的 Accept header 调用服务时,指定序列化程序的字段将被空 XML 标记存根。
示例代码(从实际问题中简化而来)。
public abstract class AbstractEntity {
private String name;
@JsonSerialize(using = MyStampSerializer.class)
private MyStamp created;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public MyStamp getCreated() {
return this.created;
}
public void setCreated(MyStamp created) {
this.created = created;
}
}
@Immutable
@JsonIgnoreProperties(ignoreUnknown = true)
@XmlRootElement(name = "entity")
public class Entity extends AbstractEntity {
public Entity() {
super();
}
}
public class MyStampSerializer extends JsonSerializer<RegistryStamp>
{
@Override
public void serialize(MyStamp stamp, JsonGenerator jgen, SerializerProvider provider)
throws IOException
{
jgen.writeStartObject();
jgen.writeStringField("name", stamp.getName());
jgen.writeNumberField("timestamp", stamp.getTimestamp().getMillis());
jgen.writeEndObject();
}
}
public class EntityXMLTest {
@Test
public void serializeAndDeserializeTest() throws InvalidClassificationException, JsonProcessingException, IOException, InvalidNameException {
Entity entity = buildTestEntity(); // Code not included.
XmlMapper xmlMapper = new XmlMapper();
xmlMapper.registerModule(new RegistryModule());
String xml = xmlMapper.writeValueAsString(collection);
assertNotNull(xml);
assertThat(xml, is("Hello"));
}
}
所以在 web-service 请求 xml 的情况下,(不正确的)输出看起来像:
<entity>
<name>theName</name>
<created />
</entity>
但是在单元测试中,(正确的)输出看起来像:
<entity>
<name>theName</name>
<created>
<name>otherName</name>
<timestamp>8647567</timestamp>
</created>
</entity>
JSON 在单元测试和 web-service.
中都符合预期
如果我注释掉序列化程序和 re-run 单元测试,输出如下:
<entity>
<created>
<name>test1</name>
<timestamp>
<dayOfYear>2</dayOfYear>
<dayOfMonth>2</dayOfMonth>
<dayOfWeek>5</dayOfWeek>
<era>1</era>
<year>1970</year>
<weekOfWeekyear>1</weekOfWeekyear>
<!-- snip ..... etc -->
</timestamp>
</created>
</entity>
所以我们显然需要序列化程序来申请 XML 以及当我在单元测试中直接调用 XMLMapper 时发生的情况。
有什么方法可以告诉 Jersery/Jackson 对 XML 和 JSON 使用序列化器吗?有没有办法找出杰克逊为什么用自定义序列化程序为字段添加 XML ?此外,有没有一种方法可以配置单元测试,使其与 dropwizard/Jersey/Jackson web-service?
的行为相同
最终我成功了。要点是:
如果你想将@JsonSerialize 与 jackson 和 dropwizard 一起使用,你可能需要使用 dropwizard-xml extension bundle that is mentioned at the very bottom of the jackson annotations page
在此之后,需要进行一些更改才能使 XML 看起来正确,主要涉及
@JacksonXmlProperty and
@JacksonXmlElementWrapper
最后的挑战是找到与我使用的 jackson 版本兼容的 dropwizard-xml 版本, 和 使用 java 1.7 编译我发现 0.9.0-30 有用。
我发现一些用
注释的字段有问题@JsonSerialize
当周围的 class 从 web-service 作为 XML 返回时,但不在单元测试中。当使用 Accept header of "application/json" 调用服务时,一切正常。当使用 "application/xml" 的 Accept header 调用服务时,指定序列化程序的字段将被空 XML 标记存根。
示例代码(从实际问题中简化而来)。
public abstract class AbstractEntity {
private String name;
@JsonSerialize(using = MyStampSerializer.class)
private MyStamp created;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public MyStamp getCreated() {
return this.created;
}
public void setCreated(MyStamp created) {
this.created = created;
}
}
@Immutable
@JsonIgnoreProperties(ignoreUnknown = true)
@XmlRootElement(name = "entity")
public class Entity extends AbstractEntity {
public Entity() {
super();
}
}
public class MyStampSerializer extends JsonSerializer<RegistryStamp>
{
@Override
public void serialize(MyStamp stamp, JsonGenerator jgen, SerializerProvider provider)
throws IOException
{
jgen.writeStartObject();
jgen.writeStringField("name", stamp.getName());
jgen.writeNumberField("timestamp", stamp.getTimestamp().getMillis());
jgen.writeEndObject();
}
}
public class EntityXMLTest {
@Test
public void serializeAndDeserializeTest() throws InvalidClassificationException, JsonProcessingException, IOException, InvalidNameException {
Entity entity = buildTestEntity(); // Code not included.
XmlMapper xmlMapper = new XmlMapper();
xmlMapper.registerModule(new RegistryModule());
String xml = xmlMapper.writeValueAsString(collection);
assertNotNull(xml);
assertThat(xml, is("Hello"));
}
}
所以在 web-service 请求 xml 的情况下,(不正确的)输出看起来像:
<entity>
<name>theName</name>
<created />
</entity>
但是在单元测试中,(正确的)输出看起来像:
<entity>
<name>theName</name>
<created>
<name>otherName</name>
<timestamp>8647567</timestamp>
</created>
</entity>
JSON 在单元测试和 web-service.
中都符合预期如果我注释掉序列化程序和 re-run 单元测试,输出如下:
<entity>
<created>
<name>test1</name>
<timestamp>
<dayOfYear>2</dayOfYear>
<dayOfMonth>2</dayOfMonth>
<dayOfWeek>5</dayOfWeek>
<era>1</era>
<year>1970</year>
<weekOfWeekyear>1</weekOfWeekyear>
<!-- snip ..... etc -->
</timestamp>
</created>
</entity>
所以我们显然需要序列化程序来申请 XML 以及当我在单元测试中直接调用 XMLMapper 时发生的情况。
有什么方法可以告诉 Jersery/Jackson 对 XML 和 JSON 使用序列化器吗?有没有办法找出杰克逊为什么用自定义序列化程序为字段添加 XML ?此外,有没有一种方法可以配置单元测试,使其与 dropwizard/Jersey/Jackson web-service?
的行为相同最终我成功了。要点是:
如果你想将@JsonSerialize 与 jackson 和 dropwizard 一起使用,你可能需要使用 dropwizard-xml extension bundle that is mentioned at the very bottom of the jackson annotations page
在此之后,需要进行一些更改才能使 XML 看起来正确,主要涉及
@JacksonXmlProperty and
@JacksonXmlElementWrapper
最后的挑战是找到与我使用的 jackson 版本兼容的 dropwizard-xml 版本, 和 使用 java 1.7 编译我发现 0.9.0-30 有用。