我正在编写一个通过Spring控制器提供REST端点的Java库。其中一个端点的有效载荷是我的 JavaRoutine
类,我为其提供了一个JSON serializerdeserializer对。这里是(略微简化)。
@JsonSerialize(using = JavaRoutine.Serializer.class)
@JsonDeserialize(using = JavaRoutine.Deserializer.class)
public class JavaRoutine {
private final String jobId;
private final List<Object> inputValues;
private final List<ExpressionType> inputTypes; // ExpressionType is defined in my lib
public JavaRoutine(String jobId) {
this.jobId = jobId;
this.inputValues = new ArrayList<>();
this.inputTypes = new ArrayList<>();
}
public String getJobId() { return jobId; }
public void addInput(Object value) {
inputValues.add(value);
inputTypes.add(value == null ? null : ExpressionType.getTypeForValue(value));
}
public static class Serializer extends StdSerializer<JavaRoutine> {
private static final ObjectMapper mapper = new ObjectMapper();
public Serializer() {
super(JavaRoutine.class);
}
@Override
public void serialize(JavaRoutine routine, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeStartObject();
gen.writeStringField("jobId", routine.jobId);
gen.writeArrayFieldStart("inputs");
int inputCount = routine.inputValues.size();
for (int i = 0; i < inputCount; i++) {
gen.writeStartObject();
gen.writeStringField("type", mapper.writeValueAsString(routine.inputTypes.get(i)));
gen.writeStringField("value", mapper.writeValueAsString(routine.inputValues.get(i)));
gen.writeEndObject();
}
gen.writeEndArray();
gen.writeEndObject();
}
}
public static class Deserializer extends StdDeserializer<JavaRoutine> {
private static final ObjectMapper mapper = new ObjectMapper();
public Deserializer() {
super(JavaRoutine.class);
}
@Override
public JavaRoutine deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
Map<String, Object> fields = p.readValueAs(new TypeReference<Map<String, Object>>() {});
JavaRoutine routine = new JavaRoutine((String) fields.get("jobId");
List<Map<String, String>> inputs = (List<Map<String, String>>) fields.get("inputs");
for (Map<String, String> input: inputs) {
ExpressionType inputType = mapper.readValue(input.get("type"), ExpressionType.class);
Object inputValue = inputType == null ? null : mapper.readValue(input.get("value"), inputType.getJavaType());
routine.addInput(inputValue);
}
return routine;
}
}
}
这样就可以了 除了当链接库的应用程序已经注册了该库的 Scala的Jackson模块,它自己也需要这个模块。简而言之,这个Jackson模块的目的是将JSON结构反序列化为Scala集合,而不是Java集合)。因此,对 p.readValueAs()
将 "input "数组反序列化为Scala列表,这将导致投射到 List<Map<String, String>>
两行后失败。
您会推荐什么解决方案?
还没有试过你的例子。但在Kubernetes上运行的多个节点在谷歌和得到了奇怪的scala集合对象时,跳转节点之间.这帮助我一半的方式。
尝试在(我猜)Deserializer中创建像下面这样的映射器。
ObjectMapper mapper.registerModule(new DefaultScalaModule());
在scala映射方面也有一些问题。对我来说,现在的顺序没有被保留。所以Lists和Maps(LinkedHashMap)会失去原来的顺序。 :(