(これは、私の問題に関するコンテキストを提供するためのあらゆる種類の背景です。「問題」までスキップしてそれを読んでから、戻って背景をざっと読みたい場合は、問題を解決してください。申し訳ありません。テキストの壁!)
データベースに保存する必要のある、ひどい、ひどいJSONがたくさんあります。基本的に、誰かが大きなXMLファイルを取得し、XMLのXPathを使用するだけで、それを1つの大きなフラットなJSONオブジェクトにシリアル化しました。これが私が意味することの例です:
元のXML:
<statistics>
<sample>
<date>2012-5-10</date>
<duration>11.2</duration>
</sample>
<sample>
<date>2012-6-10</date>
<duration>13.1</duration>
</sample>
<sample>
<date>2012-7-10</date>
<duration>10.0</duration>
</sample>
</statistics>
私が使用しなければならない恐ろしいJSON:(基本的には上からのXPathだけ)
{
"statistics":"",
"statistics/sample":"",
"statistics/sample/date":"2012-5-10",
"statistics/sample/duration":"11.2",
"statistics/sample@1":"",
"statistics/sample/date@1":"2012-6-10",
"statistics/sample/duration@1":"13.1",
"statistics/sample@2":"",
"statistics/sample/date@2":"2012-7-10",
"statistics/sample/duration@2":"10.0",
}
statistics
そして今、私はそれをと列を持つテーブルを含むデータベースに置く必要がdate
ありduration
ます。
私が現在どのようにやっているのか:(または少なくともその方法の簡単な例)
Tuple<string, string>[] jsonToColumn = // maps JSON value to SQL table column
{
new Tuple<string, string>("statistics/sample/date", "date"),
new Tuple<string, string>("statistics/sample/duration", "duration")
};
// Parse the JSON text
// jsonText is just a string holding the raw JSON
JavaScriptSerializer serializer = new JavaScriptSerializer();
Dictionary<string, object> json = serializer.DeserializeObject(jsonText) as Dictionary<string, object>;
// Duplicate JSON fields have some "@\d+" string appended to them, so we can
// find these and use them to help uniquely identify each individual sample.
List<string> sampleIndices = new List<string>();
foreach (string k in json.Keys)
{
Match m = Regex.Match(k, "^statistics/sample(@\\d*)?$");
if (m.Success)
{
sampleIndices .Add(m.Groups[1].Value);
}
}
// And now take each "index" (of the form "@\d+" (or "" for the first item))
// and generate a SQL query for its sample.
foreach (string index in compressionIndices)
{
List<string> values = new List<string>();
List<string> columns = new List<string>();
foreach (Tuple<string, string> t in jsonToColumn)
{
object result;
if (json.TryGetValue(t.Item1 + index, out result))
{
columns.Add(t.Item2);
values.Add(result);
}
}
string statement = "INSERT INTO statistics(" + string.Join(", ", columns) + ") VALUES(" + string.Join(", ", values) + ");";
// And execute the statement...
}
ただし、更新を挿入して適用する前にクエリの実行を開始し、独自のSQLステートメントを作成して実行する必要があるため、このハッカーではなくADO.NETエンティティデータモデル(またはLINQ風のもの)を使用したいと思います。ただ...面倒です。ADO.NETエンティティデータモデル(.edmx)ファイルを作成して設定しました。これで、このモデルを使用してデータベースを簡単に操作したり、データベースに書き込んだりできます。
問題/質問
問題は、JSONからADO.NETエンティティデータモデルオブジェクト(テーブルStatistic
内のサンプル/レコードを表す)に最適にマップする方法がわからないことです。statistics
最も簡単なのは、Tuple
メンバーへのポインター(Tuple<string, Statistic::*Duration>("statistics/sample/duration", &Statistic::Duration)
これがC ++の場合はala)のようなものを使用するようにリストを変更することですが、a)C#ではこれが可能だとは思わない、b)それができたとしても私はTuple
すべて異なるタイプを持っています。
ここでの私のオプションのいくつかは何ですか?Statistic
JSONをオブジェクトに最適にマッピングするにはどうすればよいですか?私はLINQの世界に少し慣れていないので、これらの値を(LINQまたは他の何かを介して)マップする方法があるかどうか疑問に思っています。
それは私がいる(そのような貧弱なJSONで作業している)最適ではない立場であり、私の現在の方法が私の状況を考えると他の何よりも優れている可能性があることを認識しています。答え。しかし、このJSONをC#オブジェクト(そして最終的にはSQLデータベース)にマッピングするためのオプションについて調べたいと思います。