Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java:用空值反序列化json数组_Java_Arrays_Json_Jackson_Gson - Fatal编程技术网

Java:用空值反序列化json数组

Java:用空值反序列化json数组,java,arrays,json,jackson,gson,Java,Arrays,Json,Jackson,Gson,我有这样的JSON: { "values": [ [ 123456, 789.0 ], [ 123457, null ] ] } “模式”是:每个值都是一个正好包含两个内容的数组,第一个是long,第二个是double(或null)。我想将其解析为一个Java对象(只是一个POJO) 我尝试了Jackson,但它有一个已知的错误,它会阻止数组中的空值工作: 我也尝试过Gson,但它显然无法处理将数组转换为J

我有这样的JSON:

{
  "values": [
    [
      123456,
      789.0
    ],
    [
      123457,
      null
    ]
  ]
}
“模式”是:每个值都是一个正好包含两个内容的数组,第一个是long,第二个是double(或null)。我想将其解析为一个Java对象(只是一个POJO)

我尝试了Jackson,但它有一个已知的错误,它会阻止数组中的空值工作:

我也尝试过Gson,但它显然无法处理将数组转换为Java对象(而不是Java数组)的想法:

下面是一个完整的测试类,它演示了Jackson和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();
        }
    }

}
import java.util.List;
导入org.codehaus.jackson.annotate.JsonCreator;
导入org.codehaus.jackson.map.ObjectMapper;
导入com.google.gson.gson;
公共类JsonTest{
私有静态最终字符串测试\u JSON=
“{\n”+
“\“值\”:[\n”+
“[\n”+
123456\n+
“789.0\n”+
“],\n”+
“[\n”+
123457\n+
“空\n”+
“]\n”+
“]\n”+
“}\n”;
公共静态类MyPojo1{
公共列表值;
公共静态类timestandandvalue{
公共长时间戳;
公共双重价值;
@JsonCreator
公共时间戳和值(列表nums){
如果(nums==null | | nums.size()<2){
抛出新的IllegalArgumentException(String.format(“至少需要两个数字(时间戳和值),而不是得到:%s”,nums));
}
this.timestamp=nums.get(0.longValue();
this.value=nums.get(1.doubleValue();
}
}
}
公共静态类MyPojo2{
公共列表值;
公共静态类timestandandvalue{
公共长时间戳;
公共双重价值;
}
}
公共静态void main(字符串[]args){
试一试{
System.out.println(新的ObjectMapper().readValue(TEST_JSON,MyPojo1.class));
}捕获(可丢弃的t){
t、 printStackTrace();
}
试一试{
System.out.println(新的Gson().fromJson(TEST_JSON,MyPojo2.class));
}捕获(可丢弃的t){
t、 printStackTrace();
}
}
}

问:将这个JSON解析为Java对象的正确方法是什么?我正在考虑使用org.json原材料构建我自己的简单解析器,因为方便的库并不那么方便。

下面是一个关于如何使用Jackson实现这一点的独立简化示例:

// 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]]
注释

  • 我使用的是
    double
    而不是原语,因此它们可以为null,并且不需要在
    ObjectMapper
    中使用其他设置
  • 您似乎正在使用
    列表
    ,但JSON中的内容看起来更像是二维
    数组
    (或
    列表
    列表)
  • 我使用的是最新版本的jacksonlibs(如Maven
    LATEST
    )。目前最新的稳定版本是2.3.2,但Maven搜索将返回最新版本2.4.1.3-请参阅的评论
  • 有关详细信息,请参阅
如果要使用,则需要进行以下更改:

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;
    }
}  
样本输出:

MyPojo2@b09697
{"values":[[123456.0,789.0],[123457.0,null]]}

似乎我试图对我的数据类型做的太多了,而库(或至少这两个库)并不真正支持它

在本例中,输入JSON具有常规结构:“values”是一个包含子数组的数组,每个子数组的大小始终为2,因此第一个项目是long,第二个是double(或null)。所以我希望我能直接把这个翻译成一个合适的POJO。这个想法是,如果一个数组有x!=2个元素,或者如果元素不是long和(可为null的)double,则这是一个解析错误;否则,它会自动转换为POJO

相反,我所做的是使用标准对数组进行手动解析。我在进行有效性检查时会手动进行,将值累积到一个列表中,然后返回该列表。作为奖励,我的POJO中的字段现在可以很容易地成为
public final
,这很好。您也可以使用Jackson或Gson将JSON转换为原语(请参见其他答案),但您仍然需要手动检查这些原语,这似乎有点违背了使用高级库的目的


我仍然认为使用库进行转换会更好,但不确定是否有支持它的库。

请注意,最新的Jackson数据绑定版本是2.4.1.3@阿列克谢·加夫里洛夫:谢谢,我一定是把他们网站上广告的最新马厩弄糊涂了。我想,您应该从
TEST\u JSON
中删除
\n
,因为这会提高可读性,不会影响行为。实际上,这会降低可读性,因为库的失败消息将无法指示错误发生在哪一行。:)
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]]}