【问题标题】:JAVA Serialization always has a null element in my arrayJAVA 序列化在我的数组中总是有一个空元素
【发布时间】:2017-03-09 17:42:53
【问题描述】:

对这种序列化/反序列化的东西相当陌生,并且一直在试图弄清楚为什么对象被序列化为数组上的空元素。

  1. 我使用通用 json 字符串将其反序列化到我的对象 A 中。
  2. 然后使用通用 ObjectMapper,我通过 objectMapper.writeValueAsString() 将该对象 A 转换为其字符串值
  3. 返回的值总是返回

    {
        [
            {[correct stuff]},
            null
        ]
    }
    

我在这里迷失了如何在此处添加 null。我用 objectMapper 尝试了无数的配置,并改变了所有涉及的类

@JsonInclude(JsonInclude.Include.NON_NULL)
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL)
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY)
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_ABSENT)
objectMapper.configure(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS, false)

谁能告诉我如何防止空值被添加到我的数组中?

感谢收看。

【问题讨论】:

  • 能分享一下A类的结构吗?
  • 请分享您的原始 json。
  • 如果您不发布代码,我们将无法解释和修复您的代码。
  • 代码在另一个未连接到网络的系统上。我正在处理数十个 POJO,因此有数千行代码,并且正在遍历所有对象,将每个 json 属性跟踪到其等效项。经过几个小时的等待,我刚刚希望找到一个灵丹妙药的解决方案。这似乎不是要在此处解决的项目,因为我无法发布代码。

标签: java json jackson


【解决方案1】:

因为所有数组项都是相关的。您不能只删除数组中间的项目。如果一个数组至少有一个元素,包括null,它仍然会被写出,因为它不是空的。

非空通常是指键值对(在对象中),其中值为空。这将告诉编组器完全忽略这对。

反序列化 JSON 后,您需要以编程方式过滤掉数组中的 null 项。

故障

myArray : null   // (Ignore)      null
myArray : []     // (Ignore)  not-null &     empty
myArray : [null] // (Include) not-null & not-empty

使用自定义的 JsonSerializer。

StringArraySerializer(序列化器)

import java.io.IOException;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;

// Derived from: http://stackoverflow.com/a/18645677
public class StringArraySerializer extends JsonSerializer<Object> {
    @Override
    public boolean isEmpty(SerializerProvider provider, Object value) {
        String[] arr = (String[]) value;
        return arr == null || arr.length == 0 || (arr.length == 1 && arr[0] == null);
    }

    @Override
    public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider)
            throws IOException, JsonProcessingException {
        String[] arr = (String[]) value;
        jgen.writeStartArray();
        for (String item : arr) {
            if (item != null) {
                jgen.writeString(item);
            }
        }
        jgen.writeEndArray();
    }
}

应用(驱动程序)

import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;

public class App {
    @SuppressWarnings("deprecation")
    public static void main(String[] args) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
            mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
            mapper.setSerializationInclusion(JsonInclude.Include.NON_ABSENT);
            mapper.configure(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS, false); // Deprecated

            Info[] list = {
                new Info("Array contains null.", new String[] { "foo", null, "bar" }),
                new Info("Array only contains null.", new String[] { null }),
                new Info("Array is empty.", new String[] { }),
                new Info("Array is null.", null)
            };

            System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(list));
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }
}

信息(POJO)

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

@JsonInclude(JsonInclude.Include.NON_NULL)
public class Info {
    private String description;

    @JsonSerialize(using = StringArraySerializer.class)
    private String[] items;

    public Info(String description, String[] items) {
        super();
        this.description = description;
        this.items = items;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String[] getItems() {
        return items;
    }

    public void setItems(String[] items) {
        this.items = items;
    }
}

输出

[ {
  "description" : "Array contains null.",
  "items" : [ "foo", "bar" ]
}, {
  "description" : "Array only contains null."
}, {
  "description" : "Array is empty."
}, {
  "description" : "Array is null."
} ]

依赖项(Gradle)

apply plugin: 'java'

repositories {
    jcenter()
}

dependencies {
    compile 'com.fasterxml.jackson.core:jackson-core:2.9.0.pr1'
    compile 'com.fasterxml.jackson.core:jackson-databind:2.9.0.pr1'
    compile 'com.fasterxml.jackson.core:jackson-annotations:2.9.0.pr1'
}

【讨论】:

    【解决方案2】:

    这是因为 null 可能是数组的一部分。考虑一个简单的对象数组 [1, null, 2, 'github']。

    当您对其进行序列化和反序列化时,您会希望保留空条目。还有其他场景,但如果不查看您的完整代码,它们可能无关紧要。

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-12
      • 1970-01-01
      • 2022-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-26
      • 1970-01-01
      相关资源
      最近更新 更多