繁体   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