Json.Net:将属性序列化/反序列化为值,而不是对象

时间:2016-11-08 06:39:24

标签: c# json serialization json.net

在另一个类中使用时,如何实现Id类的以下JSON表示?

class Car
{
    public StringId Id { get; set; }
    public string Name { get; set; }
}

class StringId
{
    public string Value { get; set; }
}

// ---------------------------------------------

// Desired representation
{ "Id": "someId", "Name": "Ford" }

// Default (undesired) representation
{ "Id" : { "Value": "someId" }, "Name": "Ford" }

2 个答案:

答案 0 :(得分:4)

您可以为StringId添加TypeConverter。 Json.NET将选择类型转换器并使用它将其转换为字符串:

[TypeConverter(typeof(StringIdConverter))]
class StringId
{
    public string Value { get; set; }
}

class StringIdConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        if (sourceType == typeof(string))
            return true;
        return base.CanConvertFrom(context, sourceType);
    }

    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        if (destinationType == typeof(StringId))
            return true;
        return base.CanConvertTo(context, destinationType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
    {
        if (value is string)
        {
            return new StringId { Value = (string)value };
        }
        return base.ConvertFrom(context, culture, value);
    }

    public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
    {
        if (destinationType == typeof(string) && value is StringId)
        {
            return ((StringId)value).Value;
        }
        return base.ConvertTo(context, culture, value, destinationType);
    }
}

如果您的字符串表示包含嵌入的数字或日期/时间数据,请务必使用传入的culture而不是默认的当前文化来转换该数据。 Json.NET将使用正确的文化which is the invariant culture by default调用转换器,从而确保生成的JSON文件可以在不同文化之间移植。

示例fiddle

但请注意,如果您使用.Net Core,则仅在Json.NET 10.0.1时添加对类型转换器的支持。从10.0.3开始,Json.NET Portable版本中不支持类型转换器。

或者,如果您不介意在类型中添加特定于Json.NET的属性,则可以使用custom JsonConverter

[JsonConverter(typeof(StringIdConverter))]
class StringId
{
    public string Value { get; set; }
}

class StringIdConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(StringId);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;
        var token = JToken.Load(reader);
        return new StringId { Value = (string)token };
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var id = (StringId)value;
        writer.WriteValue(id.Value);
    }
}

您也可以在global settings

中设置转换器

示例fiddle

答案 1 :(得分:1)

您可以覆盖ToString类的StringId方法以返回值

    public override string ToString()
    {
        return this.Value;
    }

稍后您需要TypeConverter将字符串反序列化为StringId

public class StringIdConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        if (sourceType == typeof(string))
        {
            return true;
        }
        return base.CanConvertFrom(context, sourceType);
    }


    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        if (value is string)
        {
            return new StringId(value.ToString());
        }
        return base.ConvertFrom(context, culture, value);
    }
}

使用此属性

装饰您的StringId班级
[TypeConverter(typeof(StringIdConverter))]
public class StringId{
    ...
}
相关问题