JSON.NET:如何忽略阵列中的无效元素。 我有这个JSON: { “变量1”:“ 1”, “变量2”:“ 50000”, “ arrayObject”:[null] } 我有这个存根: 公共类别1 { 公共...

问题描述 投票:0回答:2

public class Class1 { public string Variable1 { get; set; } public string Variable2 { get; set; } [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public List<ArrayObject> ArrayObject { get; set; } } public class ArrayObject { public string VariableArray1 { get; set; } public string VariableArray2 { get; set; } }

我希望忽略数组内部的空元素,最好使用JSON设置或某种转换器。因此,结果应该是该情况或空的空数组。
我一直在尝试使这项工作的代码。
class Program { static void Main(string[] args) { string json = @"{ ""Variable1"": ""1"", ""Variable2"": ""50000"", ""ArrayObject"": [null] }"; var settings = new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, }; Class1 class1 = JsonConvert.DeserializeObject<Class1>(json, settings); Console.WriteLine(class1.ArrayObject == null); Console.WriteLine(class1.ArrayObject.Count()); foreach (var item in class1.ArrayObject) { Console.WriteLine(item.VariableArray1); Console.WriteLine(item.VariableArray2); Console.WriteLine("#######################"); } } public class Class1 { public string Variable1 { get; set; } public string Variable2 { get; set; } [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public List<ArrayObject> ArrayObject { get; set; } } public class ArrayObject { public string VariableArray1 { get; set; } public string VariableArray2 { get; set; } } }

我认为使用
NullValueHandling = NullValueHandling.Ignore
会使它起作用。显然不是。有什么想法吗?

update

:我需要一个全局解决方案,我不想修改项目中的每个视图模型。
	
ssetting

NullValueHandling = NullValueHandling.Ignore

不会在避难化期间自动从JSON数组中滤波零值,因为这样做会导致数组中的其余项目被rere-indexed
,从而使无效的任何可能存储在串行化图中其他位置的数组索引。

如果您不在乎保留数组索引,并且无论如何都希望在避难所中过滤null值,那么您将需要实现一个

customJsonConverter

,例如以下内容:
c# json json.net
2个回答
5
投票
public class NullFilteringListConverter<T> : JsonConverter<List<T>> { public override List<T> ReadJson(JsonReader reader, Type objectType, List<T> existingValue, bool hasExistingValue, JsonSerializer serializer) { if (reader.MoveToContentAndAssert().TokenType == JsonToken.Null) return null; var list = existingValue as List<T> ?? (List<T>)serializer.ContractResolver.ResolveContract(objectType).DefaultCreator(); serializer.Populate(reader, list); list.RemoveAll(i => i == null); return list; } public override bool CanWrite => false; public override void WriteJson(JsonWriter writer, List<T> value, JsonSerializer serializer) => throw new NotImplementedException(); } public static partial class JsonExtensions { public static JsonReader MoveToContentAndAssert(this JsonReader reader) { if (reader == null) throw new ArgumentNullException(); if (reader.TokenType == JsonToken.None) // Skip past beginning of stream. reader.ReadAndAssert(); while (reader.TokenType == JsonToken.Comment) // Skip past comments. reader.ReadAndAssert(); return reader; } public static JsonReader ReadAndAssert(this JsonReader reader) { if (reader == null) throw new ArgumentNullException(); if (!reader.Read()) throw new JsonReaderException("Unexpected end of JSON stream."); return reader; } }

将其应用于您的模型,如下所示:
public class Class1 { public string Variable1 { get; set; } public string Variable2 { get; set; } [JsonConverter(typeof(NullFilteringListConverter<ArrayObject>))] public List<ArrayObject> ArrayObject { get; set; } }

或在设置中添加如下:

var settings = new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, Converters = { new NullFilteringListConverter<ArrayObject>() }, };

注:

由于您没有询问在序列化过程中过滤零值,但我没有实施它,但是通过更改

CanWrite => true;

并替换
WriteJson()
来实现以下操作很容易:

public override void WriteJson(JsonWriter writer, List<T> value, JsonSerializer serializer) => serializer.Serialize(writer, value.Where(i => i != null));

demo fiddles

here
  • here

    update
    
    

    我需要一个全局解决方案。如果您需要自动从每个模型中的所有可能的对象中自动过滤所有
    null
  • 值,则以下
List<T>

将完成工作: JsonConverter 将其添加到设置中,如下所示:

public class NullFilteringListConverter : JsonConverter { public override bool CanConvert(Type objectType) { if (objectType.IsArray || objectType == typeof(string) || objectType.IsPrimitive) return false; var itemType = objectType.GetListItemType(); return itemType != null && (!itemType.IsValueType || Nullable.GetUnderlyingType(itemType) != null); } object ReadJsonGeneric<T>(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var list = existingValue as List<T> ?? (List<T>)serializer.ContractResolver.ResolveContract(objectType).DefaultCreator(); serializer.Populate(reader, list); list.RemoveAll(i => i == null); return list; } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.MoveToContentAndAssert().TokenType == JsonToken.Null) return null; var itemType = objectType.GetListItemType(); var method = typeof(NullFilteringListConverter).GetMethod("ReadJsonGeneric", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public); try { return method.MakeGenericMethod(new[] { itemType }).Invoke(this, new object[] { reader, objectType, existingValue, serializer }); } catch (Exception ex) { // Wrap the TargetInvocationException in a JsonSerializerException throw new JsonSerializationException("Failed to deserialize " + objectType, ex); } } public override bool CanWrite => false; public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => throw new NotImplementedException(); } public static partial class JsonExtensions { internal static Type GetListItemType(this Type type) { // Quick reject for performance if (type.IsPrimitive || type.IsArray || type == typeof(string)) return null; while (type != null) { if (type.IsGenericType) { var genType = type.GetGenericTypeDefinition(); if (genType == typeof(List<>)) return type.GetGenericArguments()[0]; } type = type.BaseType; } return null; } } 在此转换器中,不再需要将

var settings = new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, Converters = { new NullFilteringListConverter() }, }; Class1 class1 = JsonConvert.DeserializeObject<Class1>(json, settings);

添加到[JsonConverter(typeof(NullFilteringListConverter<ArrayObject>))]。 请注意,每当使用这些设置时,都可能会重新索引所有的实例!

确保您真的希望它作为更改索引所引用的项目索引的副作用,包括索引腐败(不正确的引用),而不是彻底的。
demo小提琴#3
here
.
    

您还可以拥有一个自定义设置器,可以过滤null值。
ArrayObject

Fiddle在这里工作

Https://dotnetfiddle.net/epp0a2

    

List<T>
不会从数组中滤除零值。 但是,您可以通过在类中添加避风式回购方法来轻松执行此操作以滤除零:
ArgumentOutOfRangeException
工作演示:
Https://dotnetfiddle.net/v9yn7j

也许是System.Text.json Serializer的全局解决方案对某人有用:


2
投票

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.