2017-04-06 3 views
1

シリアライゼーションで奇妙な動作が発生しました。 けれども、私は結果は次のようになり設定JSon.Net固有のJSonConverterの問題です。空の配列は無視しなければなりません。

var SerializerSettings = new JsonSerializerSettings() { 
        NullValueHandling = NullValueHandling.Ignore,  DefaultValueHandling= DefaultValueHandling.Ignore} 
SerializerSettings.Converters.Add(new JsonArrayToNullConverter()); 

    var val = new company() 
    { 
     name = "Bobo Company Renamed" 
    } 
var str = JsonConvert.SerializeObject(val, SerializerSettings); 

を持っている: { "DOCUMENT_TYPE":2、 "場所":ヌル、...カスタムコンバータなし

、それは次のようになり {"document_type":2、 "locations":[]、...

あなたはポイントを手に入れますか?

しかし、それはヌルになるので、それはNullValueHandling = NullValueHandling.Ignore に耳を傾ける-should-しかし、明らかに、ニュートンは、)直列化されるオブジェクトの値ではなく、発行writer.WriteNull(を見て。

:(

任意の回避策は?私はこれ。おかげで、いくつかの時間を費やしてきた!

using Newtonsoft.Json; 

using System; 
using System.Collections; 
using System.Collections.Generic; 

namespace Company.Model.TypeConverters 
{ 
    /// <summary> 
    /// undo's the forced array creation because OData needs it, but for PATCH, we want no [] empty collections, it is considered to be a 
    /// </summary> 
    public class JsonArrayToNullConverter : JsonConverter 
    { 

     public override bool CanConvert(Type objectType) 
     { 
      var canConvert = objectType.IsArray || (objectType.IsGenericType && objectType.GetGenericTypeDefinition().IsAssignableFrom(typeof(IEnumerable<>))); 
      return canConvert; 
     } 
     public override bool CanRead 
     { 
      get 
      { 
       return false; 
      } 
     } 
     public override bool CanWrite 
     { 
      get 
      { 
       return true; 
      } 
     } 
     public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
     { 
      throw new NotImplementedException(); 
     } 

     public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
     { 
      var enumerator = (IEnumerable)value; 

      if (enumerator != null && enumerator.GetEnumerator().MoveNext() == false) 
      { 
       writer.WriteNull(); 
       //value = null; 
       return; 
      } 
      serializer.Serialize(writer, value); 
     } 
    } 
} 

答えて

0

ソリューションはcontractresolverを使用してJsonSerializerSettingsにそれを設定しているように見えた。

public class NullToEmptyListResolver : DefaultContractResolver 
{ 
    protected override IValueProvider CreateMemberValueProvider(MemberInfo member) 
    { 
     IValueProvider provider = base.CreateMemberValueProvider(member); 

     if (member.MemberType == MemberTypes.Property) 
     { 
      Type propType = ((PropertyInfo)member).PropertyType; 
      if (propType.IsArray || (propType.IsGenericType && 
       propType.GetGenericTypeDefinition().IsAssignableFrom(typeof(IEnumerable<>)))) 
      { 
       return new EmptyListValueProvider(provider, propType); 
      } 
     } 

     return provider; 
    } 

    public class EmptyListValueProvider : IValueProvider 
    { 
     private readonly IValueProvider innerProvider; 

     public EmptyListValueProvider(IValueProvider innerProvider, Type listType) 
     { 
      this.innerProvider = innerProvider; 
     } 

     public void SetValue(object target, object value) 
     { 
      throw new NotImplementedException(); 
     } 

     public object GetValue(object target) 
     { 
      var val = innerProvider.GetValue(target) ; 
      if (val == null) return null; 
      var enumerator = (IEnumerable)val; 
      return enumerator.GetEnumerator().MoveNext() == false ? null : val; 
     } 
    } 
+0

あなたの 'SetValue()'メソッドでは、例外をスローするのではなく 'innerProvider.SetValue(target、value); 'を呼び出す必要があります。また、[列挙子を破棄する](https://stackoverflow.com/q/232558)/37441 82)を使用した後。例えば。 [この回答](https://stackoverflow.com/a/24706061/3744182)はそれを暗にしています。 – dbc

+0

ありがとう、私の目的のために、それは書くべきではありません。 –

関連する問題