C# Can';t Json.NET是否仅使用隐式运算符自动处理值类型?
以下是我的微小自定义值类型类:C# Can';t Json.NET是否仅使用隐式运算符自动处理值类型?,c#,.net,json.net,C#,.net,Json.net,以下是我的微小自定义值类型类: public struct PhoneNumber { private readonly string _phoneNumber; public PhoneNumber(string phoneNumber) { _phoneNumber = phoneNumber; // ... lots more will happen here to validate the phone number }
public struct PhoneNumber
{
private readonly string _phoneNumber;
public PhoneNumber(string phoneNumber)
{
_phoneNumber = phoneNumber;
// ... lots more will happen here to validate the phone number
}
public static implicit operator PhoneNumber(string phoneNumber)
{
return new PhoneNumber(phoneNumber);
}
public static implicit operator string(PhoneNumber phoneNumber)
{
return phoneNumber.ToString();
}
public override string ToString()
{
return _phoneNumber;
}
}
使用字符串的隐式运算符和重写的ToString方法,我希望Json.NET能够序列化和反序列化此类的实例
然而,这样做:
var pn = new PhoneNumber("1234567890");
var json = JsonConvert.SerializeObject(pn);
。。。只返回一个空的{}
我不希望将属性应用于我的值类型类或实现自定义序列化器
有没有其他约定可以让Json.NET按照我喜欢的方式运行?C#是强类型语言。然而,人们通常在任何地方都使用string
值。在这种情况下,强类型语言的起源并没有帮助。这样的问题被称为
.NET提供了TypeConverter
来在不同类型之间转换值Newtonsoft.Json
隐式使用类型转换器
我提出了这样的解决方案:
强类型接口
首先,我们定义接口来包装原语值
/// <summary>
/// Interface to make values strongly-typed with help of TypeConverters.
/// </summary>
/// <typeparam name="TInnerType">Inner type</typeparam>
public interface IStronglyTyped<out TInnerType>
{
/// <summary>
/// Inner value.
/// </summary>
TInnerType Value { get; }
}
不幸的是,这还不够。您必须为任何自定义类型的每个属性注册自定义转换。这要复杂得多。我注意到列表底部提到了“TypeConverter”:
然后我制作了一个非常简单的自定义类型转换器:
[TypeConverter(typeof(Converter))]
public class PhoneNumber
{
private readonly string _phoneNumber;
public PhoneNumber(string phoneNumber)
{
_phoneNumber = _phoneNumber;
}
public static implicit operator PhoneNumber(string phoneNumber)
{
return new PhoneNumber(phoneNumber);
}
public static implicit operator string(PhoneNumber phoneNumber)
{
return phoneNumber.ToString();
}
public override string ToString()
{
return _phoneNumber;
}
public class Converter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return destinationType == typeof(string);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
return value.ToString();
}
}
}
现在,如果我有一个带有自定义PhoneNumber属性的类,它将按我希望的方式序列化:
public class MyClass
{
public PhoneNumber PhoneNumber { get; set; }
}
序列化:
var x = new MyClass
{
PhoneNumber = new PhoneNumber("1234567890")
};
var json = JsonConvert.SerializeObject(x);
输出:
{ "PhoneNumber": "1234567890" }
您的类没有任何属性,因此它将序列化为空对象。隐式运算符不会影响Newtonsoft序列化。您需要一个自定义类型转换器来将类序列化为字符串。您是否试图避免原始类型的困扰,并使用强类型而不是字符串?@VladimirSerykh,是的,完全正确。:)@glenebob结构是c#中的值类型。结构/对象/值类型/引用类型无关紧要。该结构没有公共属性,因此没有可序列化的内容。如果需要实体框架核心的代码段,请Ping me。这是一个很好的答案,而且非常详细。谢谢。:)没错,
TypeConverter
。使用我的解决方案,您可以将Guid
或Uri
包装到IStronglyTyped
中,以提供额外的验证和更具体的类型。这种固定的原语困扰不仅适用于字符串
值,也适用于其他常用的“原语”类型。@VladimirSerykh谢谢。你比我快了3分钟。非常令人印象深刻。
[TypeConverter(typeof(Converter))]
public class PhoneNumber
{
private readonly string _phoneNumber;
public PhoneNumber(string phoneNumber)
{
_phoneNumber = _phoneNumber;
}
public static implicit operator PhoneNumber(string phoneNumber)
{
return new PhoneNumber(phoneNumber);
}
public static implicit operator string(PhoneNumber phoneNumber)
{
return phoneNumber.ToString();
}
public override string ToString()
{
return _phoneNumber;
}
public class Converter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return destinationType == typeof(string);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
return value.ToString();
}
}
}
public class MyClass
{
public PhoneNumber PhoneNumber { get; set; }
}
var x = new MyClass
{
PhoneNumber = new PhoneNumber("1234567890")
};
var json = JsonConvert.SerializeObject(x);
{ "PhoneNumber": "1234567890" }