用户定义的结构和默认(反)序列化

jav*_*iry 5 c# serialization json deserialization

我定义了这个简单的类型:

public struct Price : IComparer<Price>, IEquatable<Price> {

    private readonly decimal _value;

    public Price(Price value) {
        _value = value._value;
    }

    public Price(decimal value) {
        _value = value;
    }

    public int Compare(Price x, Price y) {
        return x._value.CompareTo(y._value);
    }

    public int Compare(Price x, decimal y) {
        return x._value.CompareTo(y);
    }

    public int Compare(decimal x, Price y) {
        return x.CompareTo(y._value);
    }

    public bool Equals(Price other) {
        return _value.Equals(other._value);
    }

    public override bool Equals(object obj) {
        if (ReferenceEquals(null, obj))
            return false;
        return obj is Price && Equals((Price)obj);
    }

    public override int GetHashCode() {
        return _value.GetHashCode();
    }

    public static implicit operator decimal(Price p) {
        return p._value;
    }

    public static implicit operator Price(decimal d) {
        return new Price(d);
    }
}
Run Code Online (Sandbox Code Playgroud)

当我将给定的JSON反序列化时,Price它可以正常工作。但是,当我尝试序列化时,它返回一个empty { }。我的意思是,假设具有此模型:

public class Product {
    public string Name { get; set; }
    public Price Price { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

像这样反序列化JSON:

{ "Name": "Some name", "Price": 2.3 }
Run Code Online (Sandbox Code Playgroud)

给我正确的对象。但是序列化此样本:

var p = new Product { Name = "Some name", Price = 2.3 }
Run Code Online (Sandbox Code Playgroud)

创建此json:

{ "Name": "Some name", "Price": { } }
Run Code Online (Sandbox Code Playgroud)

那么,如何以及如何告诉序列化程序库(例如Json.NET和Jil)如何序列化自定义类型?

更新:

使用Json.NET的示例序列化代码

var s = JsonConvert.SerializeObject(p);
Run Code Online (Sandbox Code Playgroud)

UPDATE2: 我不想依赖于Json.NET或任何其他第三方库。因此,JsonConverter在Json.NET中使用不是答案。提前致谢。

Mat*_*391 5

现在,序列化器不知道如何序列化您的结构,因此您需要告诉它如何进行。这是针对Json.NET的方法

一种方法是添加JsonPropertyAttribute_value。这将导致像这样的json

{"Name":"Some Name","Price":{"_value":2.3}}
Run Code Online (Sandbox Code Playgroud)

另一种方法是创建自己的JsonConverter,将您的价格视为小数。一个简单的方法可能看起来像这样

class PriceConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof( decimal? );
    }

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

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        serializer.Serialize( writer, (decimal)((Price)value));
    }
}
Run Code Online (Sandbox Code Playgroud)

并且您将需要JsonConverterAttribute在结构上

[JsonConverter(typeof(PriceConverter))]
struct Price
{
    //...
}
Run Code Online (Sandbox Code Playgroud)

这会给你这样的json

{"Name":"Some Name","Price":2.3}
Run Code Online (Sandbox Code Playgroud)

两种方式都可以很好地进行序列化和反序列化,但是第二种方式可以更好地读取json。