我的JSON看起来像这样:
{
"values": [
[
123456,
789.0
],
[
123457,
null
]
]
}
“schema”是:每个值都是两个完全正确的数组,第一个是long,第二个是double(或null)。我想把它解析成一个Java对象(只是一个POJO)。
我尝试过Jackson,但它有一个已知的错误,可以阻止数组中的空值工作:https://github.com/FasterXML/jackson-databind/issues/403
我也尝试过Gson,但它显然无法应对将数组转换为Java对象(而不是Java数组)的想法:
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 3 column 6
这是一个完整的测试课程,演示杰克逊和Gson在这个简单的任务中没有工作:
import java.util.List;
import org.codehaus.jackson.annotate.JsonCreator;
import org.codehaus.jackson.map.ObjectMapper;
import com.google.gson.Gson;
public class JsonTest {
private static final String TEST_JSON =
"{\n" +
" \"values\": [\n" +
" [\n" +
" 123456,\n" +
" 789.0\n" +
" ],\n" +
" [\n" +
" 123457,\n" +
" null\n" +
" ]\n" +
" ]\n" +
"}\n";
public static class MyPojo1 {
public List<TimestampAndValue> values;
public static class TimestampAndValue {
public long timestamp;
public Double value;
@JsonCreator
public TimestampAndValue(List<Number> nums) {
if(nums == null || nums.size() < 2) {
throw new IllegalArgumentException(String.format("Expected at least two numbers (timestamp & value), instead got: %s", nums));
}
this.timestamp = nums.get(0).longValue();
this.value = nums.get(1).doubleValue();
}
}
}
public static class MyPojo2 {
public List<TimestampAndValue> values;
public static class TimestampAndValue {
public long timestamp;
public Double value;
}
}
public static void main(String[] args) {
try {
System.out.println(new ObjectMapper().readValue(TEST_JSON, MyPojo1.class));
} catch(Throwable t) {
t.printStackTrace();
}
try {
System.out.println(new Gson().fromJson(TEST_JSON, MyPojo2.class));
} catch(Throwable t) {
t.printStackTrace();
}
}
}
问题:将这个JSON解析为Java对象的正确方法是什么?我正在考虑使用org.json原材料来构建我自己的简单解析器,因为方便的库不是那么方便。
答案 0 :(得分:4)
这是一个关于如何与杰克逊这样做的简单例子:
// my pojo
public class Main {
// my property - it's a 2-dim array (might work with a List of Lists as well)
@JsonProperty(value = "values")
Double[][] values;
public static void main(String[] args) throws Exception {
ObjectMapper om = new ObjectMapper();
String json = "{\"values\":[[123456,789.0],[123457,null]]}";
Main m = om.readValue(json, Main.class);
// prints the de-serialized json
System.out.println(Arrays.deepToString(m.values));
}
}
<强>输出强>
[[123456.0, 789.0], [123457.0, null]]
备注强>
Doubles
代替原语,因此它们可以为空,并且ObjectMapper
不需要使用其他设置。List<Number>
,但您在JSON中的内容看起来更像是一个二维array
(或List
List
s。 / LI>
LATEST
)版本。最新的稳定版本目前为2.3.2,但Maven搜索将返回最新版本2.4.1.3 - 请参阅Alexey的评论。答案 1 :(得分:0)
如果您想使用GSON而不是需要更改:
MyPojo2类:
public class MyPojo2
{
public List<List<Double>> values;
public List<List<Double>> getValues() {
return values;
}
public void setValues(List<List<Double>> values) {
this.values = values;
}
}
您的JSON包含List列表,您需要类对象values
的相同数据类型。
测试类
public static void main (String[] args)
{
try
{
String json = "{\"values\":[[123456,789],[123457,null]]}";
MyPojo2 obj = null;
Gson gson = new Gson();
obj = gson.fromJson(json, MyPojo2.class);
System.out.println(obj);
System.out.println(gson.toJson(obj));
}
catch (Exception e)
{
e.printStackTrace();
}
}
示例输出:
MyPojo2@b09697
{"values":[[123456.0,789.0],[123457.0,null]]}
答案 2 :(得分:0)
我似乎试图对我的数据类型做一点太多而且库(或至少这两个)并不真正支持它。
在这种情况下,输入JSON已知具有常规结构:&#34;值&#34;是一个包含子数组的数组,每个子数组总是大小为2,这样第一项是long,第二项是double(或null)。所以我希望我能直接把它翻译成合适的POJO。这个想法是,如果某个数组以某种方式具有x!= 2个元素,或者如果元素不是long和(可空)double,则表示解析错误;否则,它会自动转换为POJO。
相反,我所使用的是使用标准JSON Java library手动解析数组。我正在手动进行有效性检查,将值累积到List中,然后返回。作为奖励,我的POJO中的字段现在可以很容易地public final
,这很好。也可以使用Jackson或Gson将JSON转换为原语(参见其他答案),但是你仍然必须手动检查这些原语,这似乎有点打败使用花哨库的点。
我仍然认为能够使用库进行此转换会更好,但不确定是否有支持它的库。