使用JSON.Net序列化数组时忽略重复项

时间:2016-06-28 02:05:10

标签: c# serialization duplicates json.net

澄清(对于处于相同情况的任何人):

请注意,我的任务是序列化现有的旧对象。因此,我宁愿调整序列化程序而不是干扰数据结构。

我相信在大多数情况下,最好直接从数据中删除重复项,如@ danny-chen的enter image description here所示。

作为我想要使用JSON.Net序列化的对象的一部分,有一个string[] files属性包含重复项:

some/path/to/f1.jpg
some/path/to/f1.jpg
some/path/to/f2.jpg
some/path/to/f3.jpg
some/path/to/f2.jpg

让我们假设这些不一定是有序的(f2, f3, f2)。

是否可以序列化数组并忽略重复项?预期结果:

{
  "files": [
    "some/path/to/f1.jpg",
    "some/path/to/f2.jpg",
    "some/path/to/f3.jpg"
  ]
}

我尝试了PreserveReferencesHandling设置,但由于数组中的每个file都是一个不同的对象,可能会重复,因此无效。

2 个答案:

答案 0 :(得分:5)

它不是序列化的一部分,它是数据处理的一部分。我建议您在序列化之前删除重复项。

string[] files = GetFiles();
data.Files = files.Distinct().ToArray(); 
//serialize data

//instead of data.Files = files; and do tricky things in serialization

答案 1 :(得分:2)

最简单的解决方案是按照@Danny Chen的建议在序列化之前过滤列表。但是,如果您在序列化期间必须这样做,则可以使用自定义JsonConverter

以下是您需要的代码:

public class RemoveDuplicatesConverter<T> : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(IEnumerable<T>).IsAssignableFrom(objectType);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteStartArray();
        foreach (T item in ((IEnumerable<T>)value).Distinct())
        {
            serializer.Serialize(writer, item);
        }
        writer.WriteEndArray();
    }

    public override bool CanRead
    {
        get { return false; }
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

要使用转换器,请在类中的列表或数组属性中添加[JsonConverter]属性,以便删除重复项,如下所示。确保转换器的通用类型与列表类型匹配。

class Foo
{
    [JsonProperty("files")]
    [JsonConverter(typeof(RemoveDuplicatesConverter<string>))]
    public string[] Files { get; set; }
}

然后正常序列化。 JSON中的列表将删除重复项,但对象中的原始列表将不受影响。

string json = JsonConvert.SerializeObject(your_object, Formatting.Indented);

小提琴:https://dotnetfiddle.net/vs2oWQ