web-dev-qa-db-ja.com

データ行をJSONオブジェクトに変換します

DataTableがありますが、これは1行しかなく、次のようになります。

   America              |  Africa               |     Japan     |   
   -------------------------------------------------------------
  {"Id":1,"Title":"Ka"} | {"Id":2,"Title":"Sf"} | {"Id":3,"Title":"Ja","Values":{"ValID":4,"Type":"Okinawa"}} 

DataTable列は、アメリカ、アフリカ、日本です。

次に、JSONが次のようになるようにDataTableをJSONに変換します。

{
"America": {
    "Id": 1,
    "Title": "Ka"
},
"Africa": {
    "Id": 2,
    "Title": "Sf"
},
"Japan": {
    "Id": 3,
    "Title": "Ja",
    "Values": {
        "ValID": 4,
        "Type": "Okinawa"
    }
  }
}  

私の試みは:

string js = JSonConvverter.Serializeobject(datatable);
var objType =  JObject.Parse(js);

しかし、それはうまくいきませんでした。どんな助けでもいただければ幸いです。

9
Sciguy13

json.net を使用していると仮定すると、特別な組み込みコンバーター DataTableConverter があり、データテーブルを 省略形式で出力します 各行が次のようにシリアル化される行の配列として質問に示されている列名と値のペア。 DataSet 用のコンバーターもありますが、 DataRow 用の特定の組み込みコンバーターはありません。したがって、DataRowを直接シリアル化する場合、Json.NETはDataRowのすべてのフィールドとプロパティをシリアル化するため、より詳細な出力が得られます。これは望ましくありません。

DataRowで使用されるよりコンパクトな形式でDataTableをシリアル化する最も簡単な方法は、 JArray.FromObject()を使用してテーブル全体をJArrayにシリアル化することです。 次に、シリアル化するDataRowと同じインデックスを持つ配列アイテムを選択します。

var rowIndex = 0;

var jArray = JArray.FromObject(datatable, JsonSerializer.CreateDefault(new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }));

var rowJToken = jArray[rowIndex];
var rowJson = rowJToken.ToString(Formatting.Indented);  // Or Formatting.None if you prefer

テーブルには1行しかないため、rowIndex0である必要があります。より一般的には、特定のDataRowのインデックスがわからない場合は、データテーブルから行番号を取得する方法を参照してください。

デモフィドル#1 ここ

あるいは、テーブル全体をシリアル化するとパフォーマンスに影響するほどテーブルが大きい場合は、 カスタムJsonConverter forDataRowを記述してオブジェクトとしてのJSONへの行:

public class DataRowConverter : JsonConverter<DataRow>
{
    public override DataRow ReadJson(JsonReader reader, Type objectType, DataRow existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException(string.Format("{0} is only implemented for writing.", this));
    }

    public override void WriteJson(JsonWriter writer, DataRow row, JsonSerializer serializer)
    {
        var table = row.Table;
        if (table == null)
            throw new JsonSerializationException("no table");
        var contractResolver = serializer.ContractResolver as DefaultContractResolver;

        writer.WriteStartObject();
        foreach (DataColumn col in row.Table.Columns)
        {
            var value = row[col];

            if (serializer.NullValueHandling == NullValueHandling.Ignore && (value == null || value == DBNull.Value))
                continue;

            writer.WritePropertyName(contractResolver != null ? contractResolver.GetResolvedPropertyName(col.ColumnName) : col.ColumnName);
            serializer.Serialize(writer, value);
        }
        writer.WriteEndObject();
    }
}

そして、次のように使用します。

var row = datatable.Rows[rowIndex];

var settings = new JsonSerializerSettings
{
    NullValueHandling = NullValueHandling.Ignore,
    Converters = { new DataRowConverter() },
};
var rowJson = JsonConvert.SerializeObject(row, Formatting.Indented, settings);

ノート:

  • 単一のDataRowをシリアル化することは理にかなっていますが、DataRowはスタンドアロンオブジェクトではないため、 deserialize 1つをシリアル化することは意味がありません。親DataTable内にのみ存在します。したがって、ReadJson()は実装されていません。

  • JsonConverter<T> はJson.NETで導入されました 11.0.1 。以前のバージョンでは、 JsonConverter から継承します。

デモフィドル#2 ここ

13
dbc

Gazziが言ったように、VisualStudioに含まれているNewtonSoft.Jsonライブラリを含める必要があります。

説明したものと同様のオブジェクトを取得するには、Country.csのような次のようなデータモデルを作成する必要があります。

[Serializable]
public class CountryModel {
   public int ID { get; set; }
   public string Title { get; set; }
   public List<ValueModel> Values { get; set; }
}

[Serializable]
public class ValueModel {
   public int ValueID { get; set; }
   public string Type { get; set; }
}

テーブルデータをこれらのモデルに変換するヘルパー関数を作成します。その後、Newtonsoft Libraryを使用して、必要に応じてデータをシリアル化/逆シリアル化できます。

2
David Price

つづり? 「SerializeObject」メソッドの呼び出しは次のようにすべきではありません。

string js = JsonConvert.SerializeObject(datatable);

データテーブルをJSON文字列に変換する の変換に関する同様の質問も参照してください。

2
Gazzi