これを行うためのより速く/より簡潔な方法があるかもしれませんが、私はJavaScriptConverter
ヘルパータイプと組み合わせることによってそれを行いました。
コンバーター(見た目よりもシンプルで、ここからインスピレーションを得ています):
private class RecordPropertyJavaScriptConverter : JavaScriptConverter
{
private static readonly Type[] _supportedTypes = new[]
{
typeof(record_group)
};
public override IEnumerable<Type> SupportedTypes
{
get { return _supportedTypes; }
}
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
if (type == typeof(record_group))
{
record_group obj = new record_group();
var kvp = dictionary.Single();
obj.Key = kvp.Key;
obj.Values = serializer.ConvertToType<IEnumerable<object>>(kvp.Value);
return obj;
}
return null;
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
var dataObj = obj as record_group;
if (dataObj != null)
{
return new Dictionary<string, object>
{
{dataObj.Key, dataObj.Values}
};
}
return new Dictionary<string, object>();
}
}
ヘルパータイプ:
private class record_group
{
public string Key;
public IEnumerable<object> Values;
}
シリアル化コード:
var groups = recList.GroupBy(r => r.Key)
.Select(g => new record_group { Key = g.Key, Values = g.Select(r => r.Value) });
JavaScriptSerializer serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new [] {new RecordPropertyJavaScriptConverter()});
string json = serializer.Serialize(groups);
出力(いくつかのタブ、私が追加した改行を含む):
[{"P_Flavor":["Berry","Cedar","Cherry","Coffee"]},
{"P_Winery":["Lyeth"]},
{"P_Body":["Elegant","Firm","Firm Tannins","Polished","Supple","Tannins"]},
{"P_Name":["A Red Blend"]},
{"P_DateReviewed":["08/31/95"]},
{"P_WineID":[34699]},
{"P_Score":[5]}]
次に、次のように(上記と同じシリアライザーインスタンスを使用して)逆シリアル化を実行できます。
var deserialized = serializer.Deserialize<IEnumerable<record_group>>(json);
var properties = deserialized.SelectMany(g => g.Values.Select(v => new record_property { Key = g.Key, Value = v }));