簡體   English   中英

Json 轉換空字符串而不是 null

[英]Json Convert empty string instead of null

我正在嘗試序列化我的結構,以便沒有獲得值的字符串獲得它們的默認值 "" 而不是 null

[JsonProperty(PropertyName = "myProperty", DefaultValueHandling = DefaultValueHandling.Populate)]
[DefaultValue("")]
public string MyProperty{ get; set; }

我在 Json 字符串中的結果:

"myProperty": null,

我想要的是

"myProperty": "",

我還嘗試創建一個沒有任何效果的轉換器,can Convert 和 WriteJson 函數由於某種原因甚至沒有觸發:

[JsonProperty(PropertyName = "myProperty")]
[JsonConverter(typeof(NullToEmptyStringConverter))]
public string MyProperty{ get; set; }

class NullToEmptyStringConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(object[]);
    }

    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)
    {
        if (value == null)
            writer.WriteValue("");
    }
}

這無助於Json.Net 如何將 null 反序列化為空字符串?

這應該有效:

var settings = new JsonSerializerSettings() { ContractResolver= new NullToEmptyStringResolver() };
var str = JsonConvert.SerializeObject(yourObj, settings);

using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System.Reflection;

public class NullToEmptyStringResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        return type.GetProperties()
                .Select(p=>{
                    var jp = base.CreateProperty(p, memberSerialization);
                    jp.ValueProvider = new NullToEmptyStringValueProvider(p);
                    return jp;
                }).ToList();
    }
}

public class NullToEmptyStringValueProvider : IValueProvider
{
    PropertyInfo _MemberInfo;
    public NullToEmptyStringValueProvider(PropertyInfo memberInfo)
    {
        _MemberInfo = memberInfo;
    }

    public object GetValue(object target)
    {
        object result =  _MemberInfo.GetValue(target);
        if (_MemberInfo.PropertyType == typeof(string) && result == null) result = "";
        return result;
            
    }

    public void SetValue(object target, object value)
    {
        _MemberInfo.SetValue(target, value);
    }
}

雖然接受的答案為我指明了正確的方向,但它看起來很脆弱。 不想擔心解析JsonProperty對象列表並自己實現IValueResolver ,因為在 Json.NET 中有完美的功能工具可用於執行此操作(它可以在基本反射中內置各種優化和極端情況處理 -基於重新實現不會)。

我的解決方案執行最少的覆蓋和解析器替換,以確保僅實際更改絕對需要更改的部分:

public sealed class SubstituteNullWithEmptyStringContractResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);

        if (property.PropertyType == typeof(string))
        {
            // Wrap value provider supplied by Json.NET.
            property.ValueProvider = new NullToEmptyStringValueProvider(property.ValueProvider);
        }

        return property;
    }

    sealed class NullToEmptyStringValueProvider : IValueProvider
    {
        private readonly IValueProvider Provider;

        public NullToEmptyStringValueProvider(IValueProvider provider)
        {
            if (provider == null) throw new ArgumentNullException("provider");

            Provider = provider;
        }

        public object GetValue(object target)
        {
            return Provider.GetValue(target) ?? "";
        }

        public void SetValue(object target, object value)
        {
            Provider.SetValue(target, value);
        }
    }
}

好吧,我的解決方案非常簡單,但不使用 JSON.NET 功能,只需將后端字段添加到您的屬性:

public class Test
{
    private string _myProperty = string.Empty;

    [JsonProperty(PropertyName = "myProperty")]
    public string MyProperty
    {
        get { return _myProperty; }
        set { _myProperty = value; }
    }
}

編輯:

在 c# 6.0 中,屬性初始化將可用:

public class Test
{
    [JsonProperty(PropertyName = "myProperty")]
    public string MyProperty { get; set;} = "";
}

@Kirill Shlenskiy 的解決方案很棒,但它沒有考慮NullValueHandling屬性。

[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string Remark{ get; set; }

這是一個改進的版本,可以處理它。 如果設置了NullValueHandling.Ignore並且值為 null,則會在 JSON 輸出中跳過它。

public sealed class SubstituteNullWithEmptyStringContractResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);
        if (property.PropertyType == typeof(string))
        {
            // Wrap value provider supplied by Json.NET.
            property.ValueProvider = new NullToEmptyStringValueProvider(property.ValueProvider, property.NullValueHandling);
        }
        return property;
    }

    sealed class NullToEmptyStringValueProvider : IValueProvider
    {
        private readonly IValueProvider Provider;
        private readonly NullValueHandling? NullHandling;

        public NullToEmptyStringValueProvider(IValueProvider provider, NullValueHandling? nullValueHandling)
        {
            Provider = provider ?? throw new ArgumentNullException("provider");
            NullHandling = nullValueHandling;
        }

        public object GetValue(object target)
        {
            if (NullHandling.HasValue 
                && NullHandling.Value == NullValueHandling.Ignore
                && Provider.GetValue(target) == null )
            {
                return null;
            }
            return Provider.GetValue(target) ?? "";
        }

        public void SetValue(object target, object value)
        {
            Provider.SetValue(target, value);
        }
    }
}

另一種解決方案(也許更清潔)。 您可以創建自己的 JsonConverter 類

class JsonNullToEmptyStringConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return true;
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    {
        return existingValue ?? string.Empty;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteValue(value ?? string.Empty);
    }
}

寫完后,您可以將其作為屬性附加到您的屬性中:

[JsonConverter(typeof(JsonNullToEmptyStringConverter))]
public string CommentType { get; set; }

原來的課不是我的。 提前感謝許多像你一樣做出貢獻的人!

我添加並解決了空問題。

Public Class JsonBooleanConverter
    Inherits JsonConverter

    Public Status As String
    Public ErrorCode As String
    <JsonProperty(NullValueHandling:=NullValueHandling.Ignore)>
    Public ErrorMessage As String
    Public Overrides ReadOnly Property CanWrite As Boolean
        Get
            Return False
        End Get
    End Property

    Public Overrides Sub WriteJson(ByVal writer As JsonWriter, ByVal value As Object, ByVal serializer As JsonSerializer)
        Throw New NotImplementedException()
    End Sub

    Public Overrides Function ReadJson(ByVal reader As JsonReader, ByVal objectType As Type, ByVal existingValue As Object, ByVal serializer As JsonSerializer) As Object

        If IsNothing(reader.Value) Then
            Return If(existingValue, String.Empty)
        End If

        Dim value = reader.Value.ToString().ToLower().Trim()

        If objectType = GetType(Boolean) Then
            Select Case value
                Case "true", "yes", "y", "1"
                    Return True

                Case Else
                    Return False
            End Select

        ElseIf objectType = GetType(DateTime) Then
            Return If(existingValue, String.Empty)
        End If
        Return If(existingValue, String.Empty)
        'Return False
    End Function

    Public Overrides Function CanConvert(ByVal objectType As Type) As Boolean
        If objectType = GetType(Boolean) Then
            Return True
        ElseIf objectType = GetType(DateTime) Then
            Return True
        End If

        Return False
    End Function

End Class

用法:

Dim listObjs As List(Of YourClass) = JsonConvert.DeserializeObject(Of List(Of YourClass))(responseFromServer, New JsonBooleanConverter())

或者:

Dim listObjs As YourClass= JsonConvert.DeserializeObject(Of YourClass)(responseFromServer, New JsonBooleanConverter())

使用 System.Text.Json 和 .NET Core 3.0 這對我有用:

var jsonSerializerOptions = new JsonSerializerOptions()
{
    IgnoreNullValues = true
};
var myJson = JsonSerializer.Serialize(myObject, 
jsonSerializerOptions );

使用 .NET 6 這是解決方案:

[JsonIgnore(條件 = JsonIgnoreCondition.WhenWritingNull)]

這里https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-ignore-properties?pivots=dotnet-6-0



與 Newtonsoft https://www.newtonsoft.com/json/help/html/NullValueHandlingIgnore.htm

, Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }

Person person = new Person
{
   Name = "Nigal Newborn",
   Age = 1
};

    string jsonIncludeNullValues = JsonConvert.SerializeObject(person, Formatting.Indented);

Console.WriteLine(jsonIncludeNullValues);
// {
//   "Name": "Nigal Newborn",
//   "Age": 1,
//   "Partner": null,
//   "Salary": null
// }

string jsonIgnoreNullValues = JsonConvert.SerializeObject(person, 
Formatting.Indented,  new JsonSerializerSettings
{
    NullValueHandling = NullValueHandling.Ignore
 } );

Console.WriteLine(jsonIgnoreNullValues);
// {
//   "Name": "Nigal Newborn",
//   "Age": 1
// }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM