我有两个这样的课程:
DataTemplate
我希望得到像这样的JSON:
public class A {
String aProp = "aProp";
public String getAProp() {
return aProp;
}
}
public class B {
String bProp = "bProp";
A a = new A();
@JsonProperty("bProp")
public String getBProp() {
return bProp;
}
@JsonSerialize(using = CustomSerializer.class)
public A getA() {
return a;
}
}
所以我写了这样的自定义{
"bProp": "bProp", // just serizlised bProp
"sProp1": "sProp1_aProp", // computed using aProp
"sProp2": "sProp2_aProp" // computed another way
}
:
JsonSerializer
但我一直收到错误:
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
public class CustomSerializer extends JsonSerializer<A> {
@Override
public void serialize(A a, JsonGenerator json, SerializerProvider provider) throws IOException {
json.writeStringField("sProp1", "sProp1_" + a.getAProp());
json.writeStringField("sProp2", "sProp2_" + a.getAProp());
}
}
除非我将com.fasterxml.jackson.core.JsonGenerationException: Can not write a field name, expecting a value
和json.writeStartObject();
放在serialize方法中(因此它会产生错误的JSON)。
所以我正在寻找像json.writeEndObject();
这样的解决方案来与自定义@JsonUnwrapped
一起使用。
答案 0 :(得分:9)
我理解你的问题,你需要的是UnwrappingBeanSerializer
。你可以看到另一个相关的SO帖子:
Different JSON output when using custom json serializer in Spring Data Rest
问题在于,您不能在一个字段中同时使用注释@JacksonUnwrapped
和@JsonSerialize
,因为当您拥有@JsonSerializer
时,杰克逊将始终编写字段名称。
以下是完整的解决方案:
public class CustomSerializer extends UnwrappingBeanSerializer {
public CustomSerializer(BeanSerializerBase src, NameTransformer transformer) {
super(src, transformer);
}
@Override
public JsonSerializer<Object> unwrappingSerializer(NameTransformer transformer) {
return new CustomSerializer(this, transformer);
}
@Override
protected void serializeFields(Object bean, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException {
A a = (A) bean;
jgen.writeStringField("custom", a.getAProp());
jgen.writeStringField("custom3", a.getAProp());
}
@Override
public boolean isUnwrappingSerializer() {
return true;
}
}
测试用例,您应该使用自定义配置重新定义对象映射器,或者使用其他方法进行研究。
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@SpringApplicationConfiguration(classes = Application.class)
public class ColorsTest {
ObjectMapper mapper = new ObjectMapper();
@Before
public void setUp(){
mapper.registerModule(new Module() {
@Override
public String getModuleName() {
return "my.module";
}
@Override
public Version version() {
return Version.unknownVersion();
}
@Override
public void setupModule(SetupContext context) {
context.addBeanSerializerModifier(new BeanSerializerModifier() {
@Override
public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer<?> serializer) {
if(beanDesc.getBeanClass().equals(A.class)) {
return new CustomSerializer((BeanSerializerBase) serializer, NameTransformer.NOP);
}
return serializer;
}
});
}
});
}
@Test
public void testSerializer() throws JsonProcessingException {
System.out.println(mapper.writeValueAsString(new B()));
}
}
B组:
public class B {
@JsonProperty("bProp")
public String getBProp() {
return "bProp";
}
@JsonUnwrapped
public A getA() {
return new A();
}
}
答案 1 :(得分:1)
我想将此帖子和解决方案添加到此处提出的问题:Using custom Serializers with JsonUnwrapperd因为原始海报正在使用JsonSerializer
。 UnwrappingBeanSerializer
的建议方法在这种情况下不会起作用。我的帖子目标略有不同,但帖子中的想法应该很容易适用于您的用例,因为它只是覆盖了一个方法而不必在属性上添加除JsonUnwrapped
之外的一堆东西。
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonUnwrapped;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.io.IOException;
public class Test {
static class A {
String aProp = "aProp";
public String getAProp() {
return aProp;
}
}
static class B {
String bProp = "bProp";
A a = new A();
@JsonProperty("bProp")
public String getBProp() {
return bProp;
}
@JsonSerialize(using = CustomSerializer.class)
@JsonUnwrapped
public A getA() {
return a;
}
}
static class CustomSerializer extends JsonSerializer<A> {
@Override
public boolean isUnwrappingSerializer() {
return true;
}
@Override
public void serialize(A a, JsonGenerator json, SerializerProvider provider) throws IOException {
json.writeStringField("sProp1", "sProp1_" + a.getAProp());
json.writeStringField("sProp2", "sProp2_" + a.getAProp());
}
}
public static void main(String... a) throws Exception {
final ObjectMapper o = new ObjectMapper();
o.enable(SerializationFeature.INDENT_OUTPUT);
System.out.println(o.writeValueAsString(new B()));
}
}