2017-09-22 5 views
2

私はAzureをデータベースの最初のEFアプローチで使用しています。 Azure Webサービスのエンティティの1つは、次のように定義されています。JsonConverterとEntityData

public class Company : EntityData 
{ 
    public string CompanyName { get; set; } 
} 

EntityDataからIdプロパティを継承します。 Idプロパティはstring型です。

クライアントで

、私は次のエンティティがあります:あなたは上記を参照することができたよう

class Company 
{ 
    [JsonConverter(typeof(IntConverter))] 
    public int Id { get; set; } 

    public string CompanyName { get; set; } 
} 

を、私はint型に文字列からIDを変換する必要があります。

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コンバータですので、私はそれを正しく作成した場合、私はわからない:

私は、次のJSONコンバーターを作成しました。私はコンバータの例を見て、彼らはreader.Valueではなく、existingValueを使用しました。私の場合、existingValueは常に0です。

上記の実装は正しいですか?

+0

'existingValue'は既存の値であり、' Company.Id'はプロパティやctorに直接割り当てられないので、常に0になります。 – Xiaoy312

+0

このトピックは議論の対象外であると私は投票しています作業コードのレビューについてそれは[CodeReview](https://codereview.stackexchange.com/help/on-topic)に属します。 –

+0

少なくとも私の質問を閉じる前に、私はDBCから大きな洞察を得ました。私はそれがトピックではないことに気づいていませんでした。あなたの助けにDBCにもう一度感謝します。 – ata6502

答えて

0

あなたのコードはです。が正しくあります。

existingValueは、親c#モデルに以前存在していた値です。これをコンバーターに渡すことで、Json.NETはpopulating既存のモデルまたは読み取り専用コレクションのときにコンバータを動作させることができます。たとえば、あなたは、コンバータと事前に割り当てられた読み取り専用のプロパティを持っている場合:

public class RootObject 
{ 
    readonly ObservableCollection<SomeClass> _collection = new ObservableCollection<SomeClass>(); 

    [JsonConverter(typeof(ObservableCollectionConverter<SomeClass>>)] 
    public ObservableCollection<SomeClass> { get { return _collection; } } 
} 

その後ObservableCollectionConverter<SomeClass>ReadJson()方法は、事前に割り当てられ_collection値を渡すと、それにアイテムを追加することができます。

言われていること、なされるべきいくつかの改善があります。WriteJson()

  1. あなたはvalue.ToString()を呼び出します。 ToString()は文化的に特定の文字列を返す可能性があります。 NumberGroupSeparatorの小数点が挿入されることがあります。その代わりに、次のようにあなたはinvariant formatにシリアル化する必要がある:

    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)); 
    } 
    
  2. 同様の修正がReadJson()で行われる必要があるだろう:

    int num; 
        if (Int32.TryParse(reader.Value.ToString(), NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out num)) 
         return num; 
        else 
         return 0; 
    
  3. あなたReadJson()が予期しないデータに対して弾力的ではありません。たとえば、渡されたJSONが実際に配列またはオブジェクト値(たとえば{"unexpectedProperty": "unexpectedValue"})を持つ場合、JsonReaderは入力の最後まで正しく進まないことになります。 reader.TokenTypeを確認し、不正なデータを適切に処理する必要があります。:

    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)); 
        } 
    

    それとも、あなたは(私はこれをお勧めしません)例外がスローされることなく、予期しないデータを消費し、廃棄することを好む場合は、JsonReader.Skip()を使用することができます。

     default: 
          Debug.WriteLine(string.Format("Unexpected token {0} at path {1}", reader.TokenType, reader.Path)); 
          reader.Skip(); 
          return 0; 
    
  4. JsonConverter.CanConvertが呼び出されませんコンバータは属性を介して適用されます。しかし、コンバータをJsonSerializerSettings.Convertersに追加した場合、trueCanConvertから返すことは問題になります。厳しいと寛容の両方を示す

    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)); 
        } 
    } 
    

    サンプルfiddle:このように、最終的なコンバータは同様に見えるかもしれません

    public override bool CanConvert(Type objectType) 
    { 
        return objectType == typeof(int) || objectType == typeof(int?); 
    } 
    

:代わりに、私はこの方法を実施NotImplementedExceptionか、適切にthrowningのいずれかをお勧めします最終的なコンバータのバージョン。

関連する問題