gpt4 book ai didi

json - 是否可以让 Jackson 将嵌套对象序列化为字符串

转载 作者:行者123 更新时间:2023-12-01 03:12:19 27 4
gpt4 key购买 nike

鉴于这些类:

@Value
private static class Message {
private final String type;
private final MyType message;
}

@Value
public class MyType {
private final String foo;
}
jackson 将产生:
{
"Type" : "Test",
"Message" : {"foo" : "bar"}
}
是否有某种类型的注释或指令我可以给 Jackson 以要求它将嵌套的复杂类型序列化为字符串,例如所需的 JSON 将是:
{
"Type" : "Test",
"Message" : "{\"foo\" : \"bar\"}"
}
我在消息字段上尝试了这两个注释:
 @JsonFormat(shape = JsonFormat.Shape.STRING)
@JsonSerialize(as=String.class)
两者都没有预期的影响。现在我的“黑客”是在构建时执行此操作:
return new Message("Test", mapper.writeValueAsString(new MyType("bar")));
我想我可以编写一个自定义序列化程序,但我想知道这是否是某种内置的标准行为。我的用例是我正在构建一个 JSON预期其中包含一个字符串消息的有效负载,该消息本身包含 JSON .
环境
Jackson 版本是 2.9.0,在 Java 10 上使用 Spring Boot 2。

最佳答案

可以使用自定义序列化程序完成:

class EscapedJsonSerializer extends StdSerializer<Object> {
public EscapedJsonSerializer() {
super((Class<Object>) null);
}


@Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
StringWriter str = new StringWriter();
JsonGenerator tempGen = new JsonFactory().setCodec(gen.getCodec()).createGenerator(str);
if (value instanceof Collection || value.getClass().isArray()) {
tempGen.writeStartArray();
if (value instanceof Collection) {
for (Object it : (Collection) value) {
writeTree(gen, it, tempGen);
}
} else if (value.getClass().isArray()) {
for (Object it : (Object[]) value) {
writeTree(gen, it, tempGen);
}
}
tempGen.writeEndArray();
} else {
provider.defaultSerializeValue(value, tempGen);
}
tempGen.flush();
gen.writeString(str.toString());
}


@Override
public void serializeWithType(Object value, JsonGenerator gen, SerializerProvider serializers, TypeSerializer typeSer) throws IOException {
StringWriter str = new StringWriter();
JsonGenerator tempGen = new JsonFactory().setCodec(gen.getCodec()).createGenerator(str);
writeTree(gen, value, tempGen);
tempGen.flush();
gen.writeString(str.toString());
}

private void writeTree(JsonGenerator gen, Object it, JsonGenerator tempGen) throws IOException {
ObjectNode tree = ((ObjectMapper) gen.getCodec()).valueToTree(it);
tree.set("@class", new TextNode(it.getClass().getName()));
tempGen.writeTree(tree);
}
}

和解串器:
class EscapedJsonDeserializer extends JsonDeserializer<Object> implements ContextualDeserializer {
private final Map<JavaType, JsonDeserializer<Object>> cachedDeserializers = new HashMap<>();

@Override
public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
throw new IllegalArgumentException("EscapedJsonDeserializer should delegate deserialization for concrete class");

}

@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException {
JavaType type = (ctxt.getContextualType() != null) ?
ctxt.getContextualType() : property.getMember().getType();
return cachedDeserializers.computeIfAbsent(type, (a) -> new InnerDeserializer(type));
}

private class InnerDeserializer extends JsonDeserializer<Object> {
private final JavaType javaType;

private InnerDeserializer(JavaType javaType) {
this.javaType = javaType;
}

@Override
public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
String string = p.readValueAs(String.class);
return ((ObjectMapper) p.getCodec()).readValue(string, javaType);
}

@Override
public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer)
throws IOException {

String str = p.readValueAs(String.class);


TreeNode root = ((ObjectMapper) p.getCodec()).readTree(str);
Class clz;
try {
clz = Class.forName(((TextNode) root.get("@class")).asText());
Object newJsonNode = p.getCodec().treeToValue(root, clz);
return newJsonNode;
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
}

该字段应使用 @JsonSerialize 和 @JsonDeserialize 进行注释(如果需要)
class Outer {
@JsonTypeInfo(include = JsonTypeInfo.As.PROPERTY, use = JsonTypeInfo.Id.CLASS)
@JsonSerialize(using = EscapedJsonSerializer.class)
@JsonDeserialize(using = EscapedJsonDeserializer.class)
public Foo val;
}

它适用于简单的集合(列表、数组)并且在某种程度上适用于多态性,尽管对于特定的多态性相关问题可能需要更复杂的解决方案。
示例输出如下所示:
{"val":"{\"foo\":\"foo\",\"@class\":\"org.test.Foo\"}"}
{"val":"{\"foo\":\"foo\",\"bar\":\"bar\",\"@class\":\"org.test.Bar\"}"}

关于json - 是否可以让 Jackson 将嵌套对象序列化为字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51141480/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com