我々(「[キー]」)。ToObject <データテーブル> Newtonsoft.Json.Linq.JObject.GetValue容易データテーブルデータ形式にノードjオブジェクトのオブジェクトを変換する方法です。このような使用は問題ではなかったです。しかし、最近になって、私たちはいくつかのケースでは、このデータ変換は、実際にいくつかの問題、あるいはエラーを持っていることがわかりました。シナリオ:
1.ときに同様の時間以下のデータソース。第2の変換データを作成する、その結果、ノードデータテーブルデータフォーマットデフォルトABC整数フィールドにデータを変換するとき、50.11失う精度は、50の整数になります
"{\" データ\ ":[{\" ABC \ ":50}、{\" ABC \ ":50.01}]}"
2.データソースは次のようです。第二のデータ型がINTに変換する際には、エラーになります。
"{\" データ\ ":[{\" ABC \ ":50}、{\" ABC \ ":\" XYZ \ "}]}"
ToObjectのJsonSerializerパラメータを使用する必要があります。シリアライザ方法を書き換えることにより、所望の効果を達成するように、列のデータ・タイプを指定します。
パブリッククラスCustomDataTableConverter:DataTableConverter
{
プライベート静的ボイドCreateRow(JsonReaderリーダ、データテーブルDT)
{
のDataRow行= dt.NewRow()。
reader.Read();
(reader.TokenType == JsonToken.PropertyName)一方
{
ストリングCOLUMNNAME =(文字列)reader.Value。
reader.Read();
DataColumnカラム= dt.Columns [COLUMNNAME]。
IF(カラム== NULL)
{
タイプcolumnDataType = GetColumnDataType(リーダー)。
カラム=新規のDataColumn(COLUMNNAME、columnDataType)。
dt.Columns.Add(列);
}
IF(column.DataType == typeof演算(データテーブル))
{
IF(reader.TokenType == JsonToken.StartArray)
{
reader.Read()。
}
データテーブル表=新しいデータテーブル()。
一方、(reader.TokenType = JsonToken.EndArray!)
{
CreateRow(リーダー、表)。
reader.Read();
}
行[COLUMNNAME] =表。
}
そうであれば(column.DataType.IsArray &&(column.DataType!= typeof演算(バイト[])))
{
であれば(reader.TokenType == JsonToken.StartArray)
{
reader.Read()。
}
リスト<オブジェクト>リスト=新しいリスト<オブジェクト>();
(!reader.TokenType = JsonToken.EndArray)一方
{
list.Add(reader.Value)。
reader.Read();
}
アレイdestinationArray = Array.CreateInstance(column.DataType.GetElementType()、list.Count)。
Array.Copy(list.ToArray()、destinationArray、list.Count)。
行[COLUMNNAME] = destinationArray。
}
他
{
オブジェクトヴァル= DBNull.Valueの。
IF(!reader.Value = NULL)
{
IF(column.DataType == typeof演算(文字列))
{
ヴァル= reader.Value.ToString()。
}
他
{
IF(string.IsNullOrEmpty(reader.Value.ToString()))
{
ヴァル= DBNull.Valueの。
}
他
{
ヴァル= Convert.ChangeType(reader.Value、column.DataType)。
}
}
行[COLUMNNAME] =ヴァル。
}
reader.Read()。
}
row.EndEdit()。
dt.Rows.Add(行)。
}
}
プライベート静的型GetColumnDataType(JsonReaderリーダ)
{
JSONTokenをtokenType = reader.TokenType。
スイッチ(tokenType)
{
ケースJsonToken.StartArray:
reader.Read();
IF(!reader.TokenType = JsonToken.StartObject)
{
リターンGetColumnDataType(リーダ).MakeArrayType();
}
typeof演算(DataTableの)を返します。
//この場所は数値型の特別な処理を必要とします。あなたが数値カラムを特定できる場合は、精度の損失を防ぐために、二重の代わりに使用することができます。列タイプは、文字列型の文字列、その後、使用、エラーを防止するためにデータの変換である場合
:ケースJsonToken.Integer
;戻りtypeof演算(ダブル)
:ケースJsonToken.Float
ケースJsonToken.String:
ケースJsonToken.Boolean:
ケースJsonToken.Date:
ケースJSONTokenをします。バイト:
リターンreader.ValueType;
ケースJsonToken.Null:
ケースJsonToken.Undefined:
リターンtypeof演算(文字列);
}
スロー新しい新JSONException($ "予期しないトークンJSON読書のDataTable間:TokenType {}");
}
プライベートの静的な無効MakeTableSchema(文字列スキーマ、データテーブルDT)
{
場合(string.IsNullOrEmpty(スキーマ)&& DT = nullを!)
{
文字列[] colinfos = schema.Trim( ' ')スプリット('、')。
foreachの(colinfosの文字列COLINFO)
{
文字列[]インフォメーション= colinfo.split( '|')。
(もし!dt.Columns.Contains(インフォ[0]))
{
dt.Columns.Add(インフォ[0]、Type.GetType( "システム。" +情報[i]の));
}
}
}
}
公共オーバーライドオブジェクトReadJson(JsonReaderリーダー、タイプobjectTypeに、オブジェクトexistingValue、JsonSerializerシリアライザ)
{
データテーブルDT = existingValueデータテーブルとして、
IF((文字列)reader.Value == "スキーマ")
{
reader.Read()。
DT =(objectTypeに== typeof演算(DataTableの))?新しいのDataTable():((DataTableの)Activator.CreateInstance(objectTypeに));
}
IF(reader.TokenType == JsonToken.PropertyName)
{
dt.TableName =(文字列)reader.Value。
reader.Read();
}
IF(reader.TokenType == JsonToken.StartObject)
{
reader.Read()。
(reader.TokenType == JsonToken.PropertyName)一方
{
MakeTableSchema((文字列)reader.Value、DT)。
reader.Read();
}
((文字列)reader.Value == "TABLENAME")場合
{
reader.Read()。
dt.TableName =(文字列)reader.Value。
reader.Read();
}
他((文字列)reader.Value == "DATA")であれば
{
reader.Read()。
IF(reader.TokenType == JsonToken.StartArray)
{
reader.Read()。
}
一方、(reader.TokenType = JsonToken.EndArray!)
{
CreateRow(リーダー、DT)。
reader.Read();
}
}
}
reader.Read()。
}
他(reader.TokenType == JsonToken.StartArray)であれば
{
reader.Read()。
一方、(!reader.TokenType = JsonToken.EndArray)
{
(リーダー、dt)を作成します。
reader.Read();
}
}
dtを返します。
}
StringBuilderのSB =新しいStringBuilderの();
foreachの(table.ColumnsでDataColumnsの列)
公共オーバーライドボイドWriteJson(JsonWriterライター、オブジェクト値、JsonSerializerシリアライザ)
{
データテーブル表=(データテーブル)値。
DefaultContractResolver contractResolver = serializer.ContractResolver DefaultContractResolverとして。
{
sb.Append(column.ColumnName + "|" + column.DataType.Name + "");
}
writer.WriteStartObject()。
writer.WritePropertyName( "SCHEMA");
serializer.Serializer(作家、sb.ToString());
writer.WritePropertyName( "TABLENAME")。
serializer.Serialize(作家、table.TableName)。
writer.WritePropertyName( "DATA");
writer.WriteStartArray();
foreachの(table.RowsでのDataRow行)
{
writer.WriteStartObject();
foreachの(row.Table.ColumnsでのDataColumn列)
{
IF((serializer.NullValueHandling!= NullValueHanding.Ignore)||((行[列]!= NULL)&&(行[列]!= DBNull.Valueの)))
{
writer.WritePropertyName((contractResolver!= NULL)? contractResolver.GetResolvedPropertyName(column.ColumnName):column.ColumnName);
serializer.Serialize(ライター、行[列])。
}
}
writer.WriteEndObject()。
}
writer.WriteEndArray()。
writer.WriteEndObject();
}
}
メソッドを呼び出します
JsonSerializerシリアライザ=新しいJsonSerializer(); serializer.Converts.Add(新しいCustomDataTableConverter()); JObject.GetValue( "[キー]")ToObject <データテーブル>(シリアライザ)。
そのようなデータは、比較的正確にデータテーブルに変換することができます。