programing

Json null 대신 빈 문자열을 변환합니다.

sourcejob 2023. 2. 8. 17:53
반응형

Json 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오브젝트 및 구현IValueResolverJson에서 사용할 수 있는 완벽한 기능을 갖춘 툴이 있다면 말이죠.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())

시스템 포함.Text.Json 및.NET Core 3.0은 다음과 같이 기능했습니다.

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

.NET 6을 사용한 해결책은 다음과 같습니다.

[JsonIgnore(상태=JsonIgnoreCondition).Writing Null)]

이쪽 https://learn.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에서 확인하실 수 있습니다.

포맷하고 있습니다.들여쓰기된 새 JsonSerializerSettings { NullValueHandling = NullValueHandling입니다.무시 }

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
// }

언급URL : https://stackoverflow.com/questions/23830206/json-convert-empty-string-instead-of-null

반응형