bestsource

Json에서 get-only 속성을 무시하는 방법이 있습니까?JsonIgnore 속성을 사용하지 않음NET?

bestsource 2023. 3. 5. 10:13
반응형

Json에서 get-only 속성을 무시하는 방법이 있습니까?JsonIgnore 속성을 사용하지 않음NET?

Json을 사용하여 get-only 속성을 무시하는 방법이 있습니까?NET 시리얼라이저는 사용하지 않습니다.JsonIgnore속성?

예를 들어 다음과 같은 get 속성을 가진 클래스가 있습니다.

    public Keys Hotkey { get; set; }

    public Keys KeyCode
    {
        get
        {
            return Hotkey & Keys.KeyCode;
        }
    }

    public Keys ModifiersKeys
    {
        get
        {
            return Hotkey & Keys.Modifiers;
        }
    }

    public bool Control
    {
        get
        {
            return (Hotkey & Keys.Control) == Keys.Control;
        }
    }

    public bool Shift
    {
        get
        {
            return (Hotkey & Keys.Shift) == Keys.Shift;
        }
    }

    public bool Alt
    {
        get
        {
            return (Hotkey & Keys.Alt) == Keys.Alt;
        }
    }

    public Modifiers ModifiersEnum
    {
        get
        {
            Modifiers modifiers = Modifiers.None;

            if (Alt) modifiers |= Modifiers.Alt;
            if (Control) modifiers |= Modifiers.Control;
            if (Shift) modifiers |= Modifiers.Shift;

            return modifiers;
        }
    }

    public bool IsOnlyModifiers
    {
        get
        {
            return KeyCode == Keys.ControlKey || KeyCode == Keys.ShiftKey || KeyCode == Keys.Menu;
        }
    }

    public bool IsValidKey
    {
        get
        {
            return KeyCode != Keys.None && !IsOnlyModifiers;
        }
    }

추가할 필요가 있습니까?[JsonIgnore]아니면 모든 get-only 속성을 무시하는 더 좋은 방법이 있을까요?

커스텀을 실장함으로써, 이것을 실시할 수 있습니다.IContractResolver연재할 때 그걸 사용했어요서브클래스를 지정하면DefaultContractResolver이 작업은 매우 쉬워집니다.

class WritablePropertiesOnlyResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        IList<JsonProperty> props = base.CreateProperties(type, memberSerialization);
        return props.Where(p => p.Writable).ToList();
    }
}

다음은 사용법을 보여주는 테스트 프로그램입니다.

using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

class Program
{
    static void Main(string[] args)
    {
        Widget w = new Widget { Id = 2, Name = "Joe Schmoe" };

        JsonSerializerSettings settings = new JsonSerializerSettings
        {
            ContractResolver = new WritablePropertiesOnlyResolver()
        };

        string json = JsonConvert.SerializeObject(w, settings);

        Console.WriteLine(json);
    }
}

class Widget
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string LowerCaseName
    {
        get { return (Name != null ? Name.ToLower() : null); }
    }
}

위의 출력은 다음과 같습니다.읽기 전용 속성이LowerCaseName는 출력에 포함되지 않습니다.

{"Id":2,"Name":"Joe Schmoe"}

JSON.net의 OptIn 모드를 사용하면 시리얼화할 속성만 장식할 수 있습니다.이 방법은 모든 읽기 전용 속성을 자동으로 제외하는 것만큼 좋지는 않지만 작업을 줄일 수 있습니다.

[JsonObject(MemberSerialization.OptIn)]
public class MyClass
{
    [JsonProperty]
    public string serializedProp { get; set; }

    public string nonSerializedProp { get; set; }
}

Udate : 리플렉션으로 다른 가능성 추가

위의 솔루션이 여전히 원하는 것과 완전히 다른 경우, 리플렉션 기능을 사용하여 사전 개체를 만들고, 그 개체는 일련화할 수 있습니다.물론 아래 예제는 단순한 클래스에서만 작동하므로 클래스에 다른 클래스가 포함되어 있는 경우 재귀가 필요합니다.이것으로 적어도 올바른 방향으로 나아갈 수 있을 것입니다.

필터링된 결과를 사전에 저장할 서브루틴:

    private Dictionary<String, object> ConvertToDictionary(object classToSerialize)
    {
        Dictionary<String, object> resultDictionary = new Dictionary<string, object>();

        foreach (var propertyInfo in classToSerialize.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
        {
            if (propertyInfo.CanWrite) resultDictionary.Add(propertyInfo.Name, propertyInfo.GetValue(classToSerialize, null));
        }

        return resultDictionary;
    }

그 용도를 나타내는 토막:

SampleClass sampleClass = new SampleClass();
sampleClass.Hotkey = Keys.A;
var toSerialize = ConvertToDictionary(sampleClass);
String resultText = JsonConvert.SerializeObject(toSerialize);

다음과 같이 계약 해결 프로그램을 사용할 수 있습니다.

public class ExcludeCalculatedResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);
        property.ShouldSerialize = _ => ShouldSerialize(member);
        return property;
    }

    internal static bool ShouldSerialize(MemberInfo memberInfo)
    {
        var propertyInfo = memberInfo as PropertyInfo;
        if (propertyInfo == null)
        {
            return false;
        }

        if (propertyInfo.SetMethod != null)
        {
            return true;
        }

        var getMethod = propertyInfo.GetMethod;
        return Attribute.GetCustomAttribute(getMethod, typeof(CompilerGeneratedAttribute)) != null;
    }
}

계산된 속성은 제외되지만 C#6 get only properties 및 set 메서드로 모든 properties를 포함합니다.

Json.net에는 속성 또는 계약 해결 프로그램 없이 속성을 조건부로 직렬화할 수 있는 기능이 있습니다.이것은, 프로젝트가 Json.net 에 의존하지 않게 하는 경우에 특히 도움이 됩니다.

Json.net 매뉴얼에 따라

속성을 조건부로 시리얼화하려면 속성과 동일한 이름의 부울을 반환하는 메서드를 추가한 다음 메서드 이름 앞에 WastSerialize를 붙입니다.메서드의 결과에 따라 속성이 직렬화되는지 여부가 결정됩니다.메서드가 true를 반환하면 속성이 serialize되고 false를 반환하면 속성이 건너뜁니다.

언급URL : https://stackoverflow.com/questions/18543482/is-there-a-way-to-ignore-get-only-properties-in-json-net-without-using-jsonignor

반응형