我有这样一个通用类:
public class Pojo<T> {
@JsonProperty("value")
public T[] values;
};
T可以包含String
、LocalDateTime
或intger
。String和intger之间的区别似乎工作正常,很可能是因为这些类型在序列化的JSON文件中表示不同。然而,当我在JSON对象中有一个日期时间时(参见示例),它无论如何都会被解析为字符串。
value
字段的实际使用类型是由输入决定的。虽然我在下面的最小示例中确实有这方面的知识,但这并不适用于我程序中该代码的所有使用。我只能依赖字段value
的值模式。
public class Main {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
String json = "{\"value\": \"2022-02-22T12:00:00\"}";
Pojo<?> deserialized = mapper.readValue(json, Pojo.class);
assert deserialized.value[0] instanceof LocalDateTime;
}
我还没有成功修补JsonTypeInfo
。如果该字段的所有值都匹配模式yyyy-MM-dd'T'hh:MM:ss
,是否有方法将该值字段解析为LocalDateTime
对象的数组?
这是你的问题——Pojo
ObjectMapper不知道要将
T
解析为什么类型。要告诉它类型,您需要使用带有TypeReference的readValue
重载,或者使用带有JavaType的重载。我发现JavaType
更容易阅读,下面是一个例子:
public class Test {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
String json = "{\"value\": \"2022-02-22T12:00:00\"}";
JavaType javaType = TypeFactory.defaultInstance().constructParametricType(Pojo.class, LocalDateTime.class);
Pojo<LocalDateTime> deserialized = mapper.readValue(json, javaType);
System.out.println(deserialized.values[0].toLocalDate());
System.out.println(deserialized.values[0].toLocalTime());
}
}
当构造参数化
JavaType
时,第一个参数是类本身,接下来是具体的泛型类型。
编辑:考虑到新的信息,我能想到的最好的方法是自定义反序列化程序,它在运行时解析类型。比如:
public class UnknownTypeDeserializer<T> extends StdDeserializer<Pojo<T>> {
private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
public UnknownTypeDeserializer() {
super((Class<?>) null);
}
@Override
public Pojo<T> deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException, JacksonException {
JsonNode node = parser.getCodec().readTree(parser);
String value = node.get("value").asText();
Pojo<T> pojo = new Pojo<>();
T[] arr;
try {
arr = (T[]) new LocalDateTime[]{LocalDateTime.parse(value, this.formatter)};
} catch (Exception exc) {
try {
arr = (T[]) new Integer[]{Integer.parseInt(value)};
} catch (NumberFormatException numberFormatException) {
arr = (T[]) new String[]{value};
}
}
pojo.values = arr;
return pojo;
}
}
这个想法是尝试解析到
LocalDateTime
,如果不可能,尝试解析到int
,如果不可能,再次保留为String
。这是非常丑陋的方法,但我只是想说明这个想法。与其捕捉异常,不如检查格式,例如使用正则表达式,并根据正则表达式匹配,解析以纠正类型。我用字符串和int测试了它,它实际上是有效的。
public class Test {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
SimpleModule simpleModule = new SimpleModule();
simpleModule.addDeserializer(Pojo.class, new UnknownTypeDeserializer<>());
mapper.registerModule(simpleModule);
String json1 = "{\"value\": \"2022-02-22T12:00:00\"}";
Pojo<?> deserialized1 = mapper.readValue(json1, Pojo.class);
System.out.println("is date - " + (deserialized1.values[0] instanceof LocalDateTime));
String json2 = "{\"value\": \"bla bla bla\"}";
Pojo<?> deserialized2 = mapper.readValue(json2, Pojo.class);
System.out.println("is string - " + (deserialized2.values[0] instanceof String));
String json3 = "{\"value\": 41}";
Pojo<?> deserialized3 = mapper.readValue(json3, Pojo.class);
System.out.println("is int - " + (deserialized3.values[0] instanceof Integer));
}
}
问题内容: 我试图读取JSON文件并将其转换为数组,但是在读取JSON文件后从数组获取空值。我正在为我的班级使用默认构造函数。 JSON文件: 本类: 问题答案: 您的Gson映射与给定的JSON不匹配。默认情况下,Gson通过 确切 名称将JSON属性映射到目标映射中的相应字段。看一眼: 和 属性名称大小写和字段名称大小写不匹配。您需要的是正确映射JSON。要么: 或通过覆盖名称匹配(这更适合J
问题内容: 我对WCF有点陌生,将尝试清楚地描述我要做什么。 我有一个使用JSON请求的WCF Web服务。我在大多数情况下都可以很好地发送/接收JSON。例如,以下代码可以正常运行,并且符合预期。 JSON已发送: WCF: 这将按预期返回带有“ Dave”的JSON对象。问题是我无法始终保证我收到的JSON与我的DataContract中的成员完全匹配。例如,JSON: 由于大小写不匹配,将无
我正在努力实现的是: 我们有一个JSON对象流进来。 我想从JSON重建一个Java对象。 我想应用转换(如更改字符串的格式和拒绝一个对象,如果满足一些条件,如'isToBe消耗'==false和可能的平坦从嵌套到线性的继承) 我希望能够将JSON对象的值存储到数据库中。 当一种新类型的JSON对象流出现时,我可以为每种类型的流运行CREATE TABLE,但我不想做任何代码更改。 换句话说,我希
我正在使用JacksonPolymorphicDeserialization,这是我的代码,它反序列化到基于“type”属性的适当类中: 它工作得很好,我的json根据“type”值变成了预期的类。 但是,我正在考虑将“type”属性从String移动到Enum,这是我的新代码,带有以下更改: 和枚举: 问题是,第二种方法不起作用。。。知道为什么吗???我可以在这里使用Enum吗??? 谢谢!
我和杰克逊有一个问题,我认为这个问题应该很容易解决,但它正在折磨我。 假设我有一个java POJO类,看起来像这样(假设我有getter和setter): 我想反序列化看起来像这样的JSON到一个User对象: Jackson给了我一些问题,因为User不是JSON中的第一级对象。我显然可以创建一个UserWrapper类,它有一个用户对象,然后使用它反序列化,但我知道一定有一个更优雅的解决方案
问题内容: 我正在使用大猩猩 websocket,并且正在计划使用json进行序列化/反序列化。 假设我有这样的结构来接收传入的消息: 和 大猩猩提供接收传入的消息。传入的消息可以是Foo或Bar,但是我不能使用和收听其他消息,这很混乱。我想要像javascript 这样的东西。如果接收到Foo,则如何处理传入消息,然后将其存储到结构中;如果接收到Bar,则将其存储到结构中? 我正在解决方案正在使