我使用Azure的数据库优先EF方法。Azure web服务中我的一个实体的定义如下:
public class Company : EntityData
{
public string CompanyName { get; set; }
}它从EntityData继承Id属性。Id属性的类型为字符串。
在客户端,我有以下实体:
class Company
{
[JsonConverter(typeof(IntConverter))]
public int Id { get; set; }
public string CompanyName { get; set; }
}正如您在上面看到的,我需要将Id从string转换为int。
我创建了以下JSON转换器:
class IntConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return true;
}
public override object ReadJson(JsonReader reader, Type objectType,
object existingValue, JsonSerializer serializer)
{
if (reader.Value == null)
return 0;
int num;
if (Int32.TryParse(reader.Value.ToString(), out num))
return num;
else
return 0;
}
public override void WriteJson(JsonWriter writer, object value,
JsonSerializer serializer)
{
serializer.Serialize(writer, value.ToString());
}
}它运行良好,但由于这是我的第一个JSON转换器,我不确定是否正确地创建了它。我看到了转换器的例子,它们使用的是existingValue而不是reader.Value。在我的例子中,existingValue总是0。
上述实施是否正确?
发布于 2017-09-22 20:31:33
你的代码基本上是正确的。
existingValue是以前存在于父c#模型中的值。通过将其传递到转换器中,Json.NET允许转换器在人口现有模型或只读集合时工作。例如,如果您的转换器具有预分配的只读属性:
public class RootObject
{
readonly ObservableCollection<SomeClass> _collection = new ObservableCollection<SomeClass>();
[JsonConverter(typeof(ObservableCollectionConverter<SomeClass>>)]
public ObservableCollection<SomeClass> { get { return _collection; } }
}然后,ReadJson()方法ObservableCollectionConverter<SomeClass>将传递预分配的_collection值,并能够将项添加到其中。
尽管如此,仍有一些改进需要改进:
WriteJson()中,你叫value.ToString()。有可能ToString()可以返回特定于文化的字符串,例如小数点可能被插入到NumberGroupSeparator中。相反,您应该按照以下方式在不变格式中序列化:
公共覆盖WriteJson(JsonWriter writer,object value,JsonSerializer序列化程序){ // Int32实现了具有ToString()重载//采用IFormatProvider规范的IConvertible接口。传递不变格式以保证//相同的序列化在所有区域性中。变量可兑换=(IConvertible)值;serializer.Serialize(writer,IConvertible}ReadJson()中进行类似的修复:
如果(Int32.TryParse(reader.Value.ToString(),NumberStyles.Integer,NumberFormatInfo.InvariantInfo,out num))返回num,否则返回0;ReadJson()无法抵御意外数据。例如,如果传入的JSON实际上有一个数组或对象值(例如{"unexpectedProperty": "unexpectedValue"}),那么JsonReader将不能正确地提前到输入的末尾。您应该检查reader.TokenType并适当地处理坏数据,例如:
公共覆盖对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序){ switch (reader.TokenType) { case JsonToken.Null:返回null;case JsonToken.Integer: // Input已经是一个整数。返回它返回( int )JToken.Load(读取器);大小写JsonToken.String:{int num;if (Int32.TryParse(reader.Value.ToString(),NumberStyles.Integer,NumberFormatInfo.InvariantInfo,out num))返回num;否则返回0;} default:在路径{1}",reader.TokenType,reader.Path)抛出新的reader.TokenType令牌{0} );}
或者,如果您喜欢在不引发异常的情况下使用和丢弃意外数据(我不建议这样做),则可以使用JsonReader.Skip():
默认值:Debug.WriteLine(string.Format(路径{1}处的“意外令牌{0}”,reader.TokenType,reader.Path));reader.Skip();返回0;JsonConverter.CanConvert。但是,如果将转换器添加到JsonSerializerSettings.Converters中,那么从CanConvert返回true将是一个问题。相反,我建议要么抛出一个NotImplementedException,要么正确地实现该方法:
公共覆盖bool CanConvert( objectType类型){返回objectType ==类型(Int)\x objectType ==类型(int?);}因此,您的最终转换器可能如下所示:
class IntConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(int) || objectType == typeof(int?);
}
public override object ReadJson(JsonReader reader, Type objectType,
object existingValue, JsonSerializer serializer)
{
switch (reader.TokenType)
{
case JsonToken.Null:
return null;
case JsonToken.Integer:
// Input was already an integer. Return it
return (int)JToken.Load(reader);
case JsonToken.String:
{
int num;
if (Int32.TryParse(reader.Value.ToString(), NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out num))
return num;
else
return 0;
}
default:
throw new JsonSerializationException(string.Format("Unexpected token {0} at path {1}", reader.TokenType, reader.Path));
}
}
public override void WriteJson(JsonWriter writer, object value,
JsonSerializer serializer)
{
// Int32 implements the IConvertible interface which has a ToString() overload
// that takes an IFormatProvider specification. Pass the invariant format to guarantee
// identical serialization in all cultures.
var convertible = (IConvertible)value;
serializer.Serialize(writer, convertible.ToString(NumberFormatInfo.InvariantInfo));
}
}示例小提琴显示了最终转换器的严格版本和容忍版本。
https://stackoverflow.com/questions/46371420
复制相似问题