Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/277.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# JsonConverter和EntityData_C#_Json_Entity Framework_Azure_Json.net - Fatal编程技术网

C# JsonConverter和EntityData

C# JsonConverter和EntityData,c#,json,entity-framework,azure,json.net,C#,Json,Entity Framework,Azure,Json.net,我正在使用Azure和数据库优先EF方法。Azure web服务中我的一个实体定义如下: public class Company : EntityData { public string CompanyName { get; set; } } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { // Int32 implements t

我正在使用Azure和数据库优先EF方法。Azure web服务中我的一个实体定义如下:

public class Company : EntityData
{
    public string CompanyName { get; set; }
}
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));
}
它从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());
    }
}
public class RootObject
{
    readonly ObservableCollection<SomeClass> _collection = new ObservableCollection<SomeClass>();

    [JsonConverter(typeof(ObservableCollectionConverter<SomeClass>>)]
    public ObservableCollection<SomeClass> { get { return _collection; } }
}
它工作正常,但因为这是我的第一个JSON转换器,我不确定我是否正确创建了它。我看到了转换器的示例,它们使用的是existingValue而不是reader.Value。在我的例子中,existingValue总是0

上述实现正确吗?

您的代码基本正确


existingValue
是以前存在于父c#模型中的值。通过将其传递到转换器中,Json.NET允许转换器在现有模型或只读集合出现时工作。例如,如果您具有带有转换器的预分配只读属性:

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());
    }
}
public class RootObject
{
    readonly ObservableCollection<SomeClass> _collection = new ObservableCollection<SomeClass>();

    [JsonConverter(typeof(ObservableCollectionConverter<SomeClass>>)]
    public ObservableCollection<SomeClass> { get { return _collection; } }
}
  • 需要在
    ReadJson()
    中进行类似的修复:

  • 您的
    ReadJson()
    无法抵御意外数据。例如,如果传入的JSON实际上有一个数组或对象值(例如
    {“unexpectedProperty”:“unexpectedValue”}
    ),那么
    JsonReader
    将不会正确地前进到输入的末尾。您应该检查并适当处理不良数据,例如:

    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));
        }
    
    或者,如果您希望在不引发异常的情况下使用和丢弃意外数据(我不建议这样做),您可以使用:

  • 通过属性应用转换器时不调用。但是,如果将转换器添加到,则从
    CanConvert
    返回
    true
    将是一个问题。相反,我建议使用
    NotImplementedException
    或正确实现该方法:

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(int) || objectType == typeof(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));
        }
    }
    

    显示最终转换器的严格版本和宽容版本的示例。

    现有值是现有值,并且由于
    Company.Id
    从未直接分配给属性或从ctor分配,因此它将始终为0。我投票将此问题作为离题题结束,因为它是关于检查工作代码的。至少在结束我的问题之前,我从DBC得到了很好的见解,这是很好的:)我没有意识到它离题了。再次感谢DBC的帮助。@ata6502-问题不会被删除,它会被移动到。这是一个写得很好的问题,但对那个网站来说可能更好。