オブジェクトをDictionary
(JsonConvert.DeserializeObject<IDictionary<string,object>>(json)
)に逆シリアル化すると、ネストされたオブジェクトはJObject
sに逆シリアル化されます。ネストされたオブジェクトをDictionary
sに強制的に逆シリアル化することは可能ですか?
CustomCreationConverter
実装を提供することにより、すべてのネストされたオブジェクトをDictionary<string,object>
に変換する方法を見つけました。
class MyConverter : CustomCreationConverter<IDictionary<string, object>>
{
public override IDictionary<string, object> Create(Type objectType)
{
return new Dictionary<string, object>();
}
public override bool CanConvert(Type objectType)
{
// in addition to handling IDictionary<string, object>
// we want to handle the deserialization of dict value
// which is of type object
return objectType == typeof(object) || base.CanConvert(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.StartObject
|| reader.TokenType == JsonToken.Null)
return base.ReadJson(reader, objectType, existingValue, serializer);
// if the next token is not an object
// then fall back on standard deserializer (strings, numbers etc.)
return serializer.Deserialize(reader);
}
}
class Program
{
static void Main(string[] args)
{
var json = File.ReadAllText(@"c:\test.json");
var obj = JsonConvert.DeserializeObject<IDictionary<string, object>>(
json, new JsonConverter[] {new MyConverter()});
}
}
代替/更新:
String
sの辞書の辞書を逆シリアル化する必要があり、現在のJson.NET(5.0)では、CustomConverterを作成する必要はなく、(VB.Netで)使用しました:
JsonConvert.DeserializeObject(Of IDictionary(Of String, IDictionary(Of String, String)))(jsonString)
または、C#の場合:
JsonConvert.DeserializeObject<IDictionary<String, IDictionary<String, String>>(jsonString);
このQに遭遇したとき、私は非常に似ていますが少し複雑なニーズがありました。最初は、受け入れられた回答を適応できるかもしれないと思ったのですが、それは少し複雑に思え、結局別のアプローチをとることになりました。レガシーC++ APIの上に最新のJSONレイヤーを配置しようとしました。詳細は割愛します。要件は次のように要約されます。
JSONオブジェクトはDictionary<string,object>
になります。
JSON配列はList<object>
になります。
JSON値は、対応するプリミティブCLR値になります。
オブジェクトと配列は無限にネストできます。
最初にリクエスト文字列をNewtonsoft JSONオブジェクトに逆シリアル化してから、上記の要件に従ってメソッドを呼び出して変換します。
var jsonObject = JsonConvert.DeserializeObject(requestString);
var apiRequest = ToApiRequest(jsonObject);
// call the legacy C++ API ...
APIが期待する構造に変換する私のメソッドは次のとおりです。
private static object ToApiRequest(object requestObject)
{
switch (requestObject)
{
case JObject jObject: // objects become Dictionary<string,object>
return ((IEnumerable<KeyValuePair<string, JToken>>) jObject).ToDictionary(j => j.Key, j => ToApiRequest(j.Value));
case JArray jArray: // arrays become List<object>
return jArray.Select(ToApiRequest).ToList();
case JValue jValue: // values just become the value
return jValue.Value;
default: // don't know what to do here
throw new Exception($"Unsupported type: {requestObject.GetType()}");
}
}
私は誰かがこのアプローチが役に立つと思うことを望みます。