일반 JsonConverter를 사용하는 C #의 JSON 직렬화 가능한 문자열 열거 형
StringEnumeration
아래 코드에서 제네릭 클래스로 변경하려면 어떻게 하면 클래스의 인스턴스가 연결된 문자열 값이있는 직렬화 가능한 열거 형인 것처럼 사용할 수 있도록 속성이 ConsensusState
필요하지 않습니다 JsonConverter
.
내가 사용하고 StringEnumeration
인스턴스를 점검 할 수 있도록 ConsensusState
전년도 string
조건문 개체를 또는 콘솔에 직접 인쇄 string
도에서 속성으로 사용할 수 있지만, 값 Serializable
클래스. 직렬화는 System.Text.Json.Serialization
.
수업은 다음과 같습니다.
/// <summary>Consensus state returned by the server.</summary>
[Serializable]
[JsonConverter(typeof(StringEnumerationConverter<ConsensusState>))]
public class ConsensusState : StringEnumeration
{
/// <summary>Connecting.</summary>
public static readonly ConsensusState Connecting = new ConsensusState("connecting");
/// <summary>Syncing blocks.</summary>
public static readonly ConsensusState Syncing = new ConsensusState("syncing");
/// <summary>Consensus established.</summary>
public static readonly ConsensusState Established = new ConsensusState("established");
private ConsensusState(string value) : base(value) { }
}
/// <summary>JsonConverter used in string enumeration serialization.</summary>
public class StringEnumerationConverter<T> : JsonConverter<T>
{
/// <summary>Read the string value.</summary>
/// <param name="reader">Reader to access the encoded JSON text.</param>
/// <param name="typeToConvert">Type of the object to deserialize.</param>
/// <param name="options">Options for the deserialization.</param>
/// <returns>Underlying string enumeration type.</returns>
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return (T)Activator.CreateInstance(typeof(T), BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { reader.GetString() }, null, null);
}
/// <summary>Write the string value.</summary>
/// <param name="writer">Writer to encode the JSON text.</param>
/// <param name="value">Object to serialize.</param>
/// <param name="options">Options for the serialization.</param>
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
{
writer.WriteStringValue((string)typeof(T).GetProperty("Value").GetValue(value, null));
}
}
/// <summary>Abstract base class used in string enumerations.</summary>
public abstract class StringEnumeration
{
/// <summary>Associated value.</summary>
public string Value { get; set; }
/// <summary>Initializes the enumeration from a string.</summary>
/// <param name="value">The associated value.</param>
public StringEnumeration(string value) { Value = value; }
/// <summary>Implicit conversion to string.</summary>
/// <param name="obj">And StringEnumeration object.</param>
/// <returns>string object.</returns>
public static implicit operator string(StringEnumeration obj)
{
return obj.Value;
}
/// <summary>Get the string associated value.</summary>
/// <returns>string object.</returns>
public override string ToString()
{
return Value;
}
/// <summary>Test whether a StringEnumeration is equal to another object.</summary>
/// <param name="a">StringEnumeration object.</param>
/// <param name="b">Another object.</param>
/// <returns>true if the two objects are equal.</returns>
public static bool operator ==(StringEnumeration a, object b)
{
var other = b as StringEnumeration;
if (other is null)
{
return false;
}
return a.Value == other.Value;
}
/// <summary>Test whether a StringEnumeration is different to other object.</summary>
/// <param name="a">StringEnumeration object.</param>
/// <param name="b">Another object.</param>
/// <returns>true if the two objects are different.</returns>
public static bool operator !=(StringEnumeration a, object b)
{
var other = b as StringEnumeration;
if (other is null)
{
return true;
}
return a.Value != other.Value;
}
/// <summary>Test whether a StringEnumeration is equal to another object.</summary>
/// <param name="obj">Another object.</param>
/// <returns>true if the objects are equal.</returns>
public override bool Equals(object obj)
{
var other = obj as StringEnumeration;
if (other is null)
{
return false;
}
return Value == other.Value;
}
/// <summary>Get the hash code of the associated value.</summary>
/// <returns>An integer value representing the hash of the associated value.</returns>
public override int GetHashCode()
{
return Value.GetHashCode();
}
}
답변
1 rraallvv
StringEnumeration
아래 의 구현은 서브 클래스가 마치 문자열 열거 형인 것처럼 동작하도록 허용하고 속성을 사용하여 각 필드에 대한 문자열 관련 값을 지정할 수있는 것과 같은 삶의 질을 향상시킵니다 JsonStringValue()
.
/// <summary>Attribute to assign the string value of fields in StringEnumeration.</summary>
[AttributeUsage(AttributeTargets.Field)]
public class JsonStringValue : Attribute
{
/// <summary>String value.</summary>
public string Value;
/// <summary>Initializes the Attribute instance to a given value.</summary>
public JsonStringValue(string value)
{
Value = value;
}
}
/// <summary>JsonConverter used in string enumeration serialization.</summary>
public class StringEnumerationConverter : JsonConverter<StringEnumeration>
{
/// <summary>Whether a type is a subclass of <c>StringEnumeration</c>.</summary>
/// <param name="typeToConvert">Type to check.</param>
/// <returns>True if is a subclass.</returns>
public override bool CanConvert(Type typeToConvert)
{
return typeof(StringEnumeration).IsAssignableFrom(typeToConvert);
}
/// <summary>Read the string value.</summary>
/// <param name="reader">Reader to access the encoded JSON text.</param>
/// <param name="typeToConvert">Type of the object to deserialize.</param>
/// <param name="options">Options for the deserialization.</param>
/// <returns>Underlying string enumeration type.</returns>
public override StringEnumeration Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var obj = (StringEnumeration)FormatterServices.GetUninitializedObject(typeToConvert);
obj.Value = reader.GetString();
return obj;
}
/// <summary>Write the string value.</summary>
/// <param name="writer">Writer to encode the JSON text.</param>
/// <param name="value">Object to serialize.</param>
/// <param name="options">Options for the serialization.</param>
public override void Write(Utf8JsonWriter writer, StringEnumeration value, JsonSerializerOptions options)
{
writer.WriteStringValue(value);
}
}
/// <summary>Abstract base class used in string enumerations.</summary>
public abstract class StringEnumeration
{
/// <summary>Associated value.</summary>
public string Value { get; set; }
/// <summary>Initializes all static fields in subclasses.</summary>
static StringEnumeration()
{
var types = typeof(StringEnumeration).Assembly.GetTypes();
foreach (var type in types)
{
if (type.BaseType == typeof(StringEnumeration))
{
var fields = type.GetFields(BindingFlags.Public | BindingFlags.Static);
foreach (var field in fields)
{
var attribute = field.GetCustomAttribute<JsonStringValue>();
var name = attribute is null ? field.Name : attribute.Value;
var value = (StringEnumeration)FormatterServices.GetUninitializedObject(type);
value.Value = name;
field.SetValue(null, value);
}
}
}
}
/// <summary>Implicit conversion to string.</summary>
/// <param name="obj">And StringEnumeration object.</param>
/// <returns>string object.</returns>
public static implicit operator string(StringEnumeration obj)
{
if (obj is null)
{
return null;
}
return obj.ToString();
}
/// <summary>Get the string associated value.</summary>
/// <returns>string object.</returns>
public override string ToString()
{
return Value;
}
/// <summary>Test whether a StringEnumeration is equal to another object.</summary>
/// <param name="a">StringEnumeration object.</param>
/// <param name="b">Another object.</param>
/// <returns>true if the two objects are equal.</returns>
public static bool operator ==(StringEnumeration a, object b)
{
if (a is null)
{
return b is null;
}
return !(b is null) && a.Value == b.ToString();
}
/// <summary>Test whether a StringEnumeration is different to other object.</summary>
/// <param name="a">StringEnumeration object.</param>
/// <param name="b">Another object.</param>
/// <returns>true if the two objects are different.</returns>
public static bool operator !=(StringEnumeration a, object b)
{
return !(a == b);
}
/// <summary>Test whether a StringEnumeration is equal to another object.</summary>
/// <param name="obj">Another object.</param>
/// <returns>true if the objects are equal.</returns>
public override bool Equals(object obj)
{
return this == obj;
}
/// <summary>Get the hash code of the associated value.</summary>
/// <returns>An integer value representing the hash of the associated value.</returns>
public override int GetHashCode()
{
return Value.GetHashCode();
}
}
사용 방법은 다음과 같습니다.
/// <summary>Consensus state returned by the server.</summary>
[Serializable]
[JsonConverter(typeof(StringEnumerationConverter))]
public class ConsensusState : StringEnumeration
{
/// <summary>Connecting.</summary>
[JsonStringValue("connecting")]
public static ConsensusState Connecting;
/// <summary>Syncing blocks.</summary>
[JsonStringValue("syncing")]
public static ConsensusState Syncing;
/// <summary>Consensus established.</summary>
[JsonStringValue("established")]
public static ConsensusState Established;
}