2017-09-04 4 views
2

ユーザーがjsonファイルをアップロードできる関数を作成しようとしています。オブジェクトを処理するためのJSONを作成します。いくつかのプロパティは常に同じで、いくつかの違いがあります

jsonファイル内の各行には、異なるnrのプロパティ(列)を設定できます。 これらのプロパティのうちの5つは常に同じであるため、それらをオブジェクトに逆シリアル化する必要があります。残りのプロパティは辞書などに入れなければなりません。ここで

は、JSONの例である:ここで

[{ 
     "Projekt": "Bakker Bouw Service", 
     "Ruimte": "Hoofdgebouw", 
     "Apparaat": { 
      "project": "Bosboom001", 
      "versie": "812" 
     }, 
     "Apparaat naam": "", 
     "Status": "Goedgekeurd", 
     "Testname1": "", 
     "Testname3": "2000-01-04T10:37:00+01:00", 
     "Testname7": "2001-01-03T00:00:00+01:00" 
    }, { 
     "Projekt": "Bakker Bouw Service", 
     "Ruimte": "Hoofdgebouw", 
     "Apparaat": { 
      "project": "Vlaams003", 
      "versie": "713" 
     }, 
     "Apparaat naam": "", 
     "Status": "Goedgekeurd", 
     "Testname1": "Slecht", 
     "Testname7": "2000-01-04T10:37:00+01:00", 
     "Testname9": "2001-01-03T00:00:00+01:00", 
     "Testname16": "18MOhm", 
     "Testname23": "OK" 
    }, { 
     "Projekt": "Bakker Bouw Service", 
     "Ruimte": "Hoofdgebouw", 
     "Apparaat": { 
      "project": "Vlaams017", 
      "versie": "73" 
     }, 
     "Apparaat naam": "GDR34Z5", 
     "Status": "Afgekeurd", 
     "Testname7": "2000-01-04T10:37:00+01:00", 
     "Testname10": "0,012mA", 
     "Testname16": "200MOhm", 
     "Testname23": "200MOhm", 
     "Testname25": "Afgekeurd", 
     "Testname31": "0,01mA" 
    } 
] 

はにdeserialzeするクラスです:

public class KeuringRegel 
{ 
    public string Projekt { get; set; } 
    public string Ruimte { get; set; } 
    public Apparaat Apparaat { get; set; } 
    [JsonProperty(PropertyName = "Apparaat naam")] 
    public string Apparaatnaam { get; set; } 
    public string Status { get; set; } 
    public Dictionary<string, object> testNames { get; set; } 
} 

public class Apparaat 
{ 
    public string project { get; set; } 
    public string versie { get; set; } 
} 

そして、ここでJSONが正常にデシリアライズコントローラ

public IActionResult Upload(IFormFile file) 
    { 
     string fileContent = null; 
     using (var reader = new StreamReader(file.OpenReadStream())) 
     { 
      fileContent = reader.ReadToEnd(); 
     } 
     List<KeuringRegel> keuringRegelList = JsonConvert.DeserializeObject<List<KeuringRegel>>(fileContent); 
     //More stuff here 
    } 

ですが、 testNames値は常にnullです。私は理由を理解しています。なぜなら、JsonファイルにはtestNamesというプロパティがないからです。しかし、私は何をしたいのですか?私はJsonの専門家ではない。

+0

完全な例がありますか? –

+0

https://codebeautify.org/jsonviewer –

+1

おそらく、JSONの形式を変更できるかどうか、あるいはそのまま解析する必要があるかどうかを尋ねることを意味していました。 – CodeCaster

答えて

3

あなたがこれを行うことができます一つの方法は、補足的な値としてのみtestNameNNNNエントリがあると仮定して、このようなJsonExtensionDataAttributeを使用することです:

public class KeuringRegel 
{ 
    public string Projekt { get; set; } 
    public string Ruimte { get; set; } 
    public Apparaat Apparaat { get; set; } 
    [JsonProperty(PropertyName = "Apparaat naam")] 
    public string Apparaatnaam { get; set; } 
    public string Status { get; set; } 
    [JsonExtensionData()] 
    public Dictionary<string, object> testNames { get; set; } 
} 

これは、値の玉葉が落ちないあなたを与えるだろう他の特性の一つに:

enter image description here

それは「鈍器」のビットだが、あなたは常にいくつかのポストprocessinを行うことができgを返して、の返されたインスタンスで、testNamesから誤ったエントリを削除します。パターンtestNameNNNNと一致しないもの)。

あなたのJSON したがって含まになるだろうパターンtestNameNNNNと一致しない、あなたはtestNamesプロパティにカスタムクラスを実装することができ、物事を含まれていない場合:

public class KeuringRegel 
{ 
    public string Projekt { get; set; } 
    public string Ruimte { get; set; } 
    public Apparaat Apparaat { get; set; } 
    [JsonProperty(PropertyName = "Apparaat naam")] 
    public string Apparaatnaam { get; set; } 
    public string Status { get; set; } 
    [JsonExtensionData()] 
    public TestNames testNames { get; set; } 
} 

public class TestNames : Dictionary<string, object> 
{ 
    public new void Add(string key, object value) 
    { 
     if (key.StartsWith("testname", StringComparison.OrdinalIgnoreCase)) 
     { 
      base.Add(key, value); 
     } 
    } 
} 

これは、という各項目をチェックしますtestNamesディクショナリに追加され、(JSONに項目があった私のコメントのように)"badgerBadgetCatCat": 3というパターンには一致しません。ここで

+1

私はカスタムJsonConverterを探していましたが、すぐに諦めました。これが最も実用的な解決策です。 JSON.NETはJSONからではなく、クラスのプロパティから逆シリアル化します。したがって、コンバータは 'TestnameNNN'トークンを決して見ないでしょう。 – CodeCaster

+1

優れたソリューション!ありがとう!この解決策について長所と短所がありますか?それは物事を行うための推奨された方法ですか? JSON形式を変更する方が良いですか?たぶん良いサンプルのdocや何かへのリンク –

+1

@Kipei明らかに、それが生成されたJSONを適切にフォーマットするのは分かりやすいことです。番号付きのプロパティは、悪いデザインの特徴です。 – CodeCaster

0

UこのJSONが構築されてい

internal class Program 
    { 
     private static void Main(string[] args) 
     { 
      var str = @"[{ 
     ""Projekt"": ""Bakker Bouw Service"", 
     ""Ruimte"": ""Hoofdgebouw"", 
     ""Apparaat"": { 
      ""project"": ""Bosboom001"", 
      ""versie"": ""812"" 
     }, 
     ""Apparaat naam"": """", 
     ""Status"": ""Goedgekeurd"", 
     ""Testname1"": """", 
     ""Testname3"": ""2000-01-04T10:37:00+01:00"", 
     ""Testname7"": ""2001-01-03T00:00:00+01:00"" 
    }, { 
     ""Projekt"": ""Bakker Bouw Service"", 
     ""Ruimte"": ""Hoofdgebouw"", 
     ""Apparaat"": { 
      ""project"": ""Vlaams003"", 
      ""versie"": ""713"" 
     }, 
     ""Apparaat naam"": """", 
     ""Status"": ""Goedgekeurd"", 
     ""Testname1"": ""Slecht"", 
     ""Testname7"": ""2000-01-04T10:37:00+01:00"", 
     ""Testname9"": ""2001-01-03T00:00:00+01:00"", 
     ""Testname16"": ""18MOhm"", 
     ""Testname23"": ""OK"" 
    }, { 
     ""Projekt"": ""Bakker Bouw Service"", 
     ""Ruimte"": ""Hoofdgebouw"", 
     ""Apparaat"": { 
      ""project"": ""Vlaams017"", 
      ""versie"": ""73"" 
     }, 
     ""Apparaat naam"": ""GDR34Z5"", 
     ""Status"": ""Afgekeurd"", 
     ""Testname7"": ""2000-01-04T10:37:00+01:00"", 
     ""Testname10"": ""0,012mA"", 
     ""Testname16"": ""200MOhm"", 
     ""Testname23"": ""200MOhm"", 
     ""Testname25"": ""Afgekeurd"", 
     ""Testname31"": ""0,01mA"" 
    } 
]"; 

      var sw = Stopwatch.StartNew(); 

      var result = Mapper.Map(str); 


      sw.Stop(); 
      Console.WriteLine($"Deserialized at {sw.ElapsedMilliseconds} ms ({sw.ElapsedTicks} tiks)"); 
     } 

     public static class Mapper 
     { 
      static Mapper() 
      { 
       List<string> names = new List<string>(); 
       IEnumerable<PropertyInfo> p = typeof(KeuringRegel).GetProperties().Where(c => c.CanRead && c.CanWrite); 
       foreach (var propertyInfo in p) 
       { 
        var attr = propertyInfo.GetCustomAttribute<JsonPropertyAttribute>(); 
        names.Add(attr != null ? attr.PropertyName : propertyInfo.Name); 
       } 

       Properties = names.ToArray(); 
      } 


      private static string[] Properties { get; } 



      public static KeuringRegel[] Map(string str) 
      { 
       var keuringRegels = JsonConvert.DeserializeObject<KeuringRegel[]>(str); 
       var objs = JsonConvert.DeserializeObject(str) as IEnumerable; 
       var objectList = new List<JObject>(); 
       foreach (JObject obj in objs) 
        objectList.Add(obj); 

       for (var i = 0; i < keuringRegels.Length; i++) 
       { 
        keuringRegels[i].testNames = new Dictionary<string, object>(); 
        foreach (var p in objectList[i].Children().OfType<JProperty>().Where(c => !Properties.Contains(c.Name)).ToArray()) 
         keuringRegels[i].testNames.Add(p.Name, p.Value); 
       } 

       return keuringRegels; 
      } 
     } 


     public class KeuringRegel 
     { 
      public string Projekt { get; set; } 
      public string Ruimte { get; set; } 
      public Apparaat Apparaat { get; set; } 

      [JsonProperty(PropertyName = "Apparaat naam")] 
      public string Apparaatnaam { get; set; } 

      public string Status { get; set; } 
      public Dictionary<string, object> testNames { get; set; } 
     } 

     public class Apparaat 
     { 
      public string project { get; set; } 
      public string versie { get; set; } 
     } 
    } 
+0

あなたのアプローチを説明してください。 – CodeCaster

関連する問題