例如,我有一些课程:
class User
{
int Id {get; set;}
string Name {get; set;}
}
class Venue
{
int Id {get; set;}
string Adress {get; set;}
}
class Message
{
string Text {get; set;}
int FromId {get; set;}
}
我从网上拿了json:
[%user% => {id: 1, name: "Alex"}, %user% => {id: 5, name: "John"}]
我可以解析它:
var myObjects = JsonConvert.DeserializeObject<Dictionary<string, User>>(json);
但如果有一个json:
[%user% => {id: 1, name: "Alex"}, %venue% => {id: 465, adress: "Thomas at 68th Street"}, %message% => {text: "hello", fromId: 78}]
我可以按键%user%= User,%venue%= Venue等定义类型。
但是我怎么解析呢?
提前致谢!
更新
我目前的解决方案:
private JsonSerializerSettings _jsonSettings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All,
TypeNameAssemblyFormat = FormatterAssemblyStyle.Full
};
string myJson = "{\"%user%\":{\"id\" : 5, \"name\" : \"John\"}, \"%venue%\":{\"id\" : \"5f56de\", \"adress\": \"Thomas at 68th Street\"}}";
Dictionary<string, object> dict =
JsonConvert.DeserializeObject<Dictionary<string, object>>
(myJson, _jsonSettings);
Dictionary<string, object> d = new Dictionary<string, object>();
foreach(var o in dict)
{
string json = (string)o.Value.ToString();
switch (o.Key)
{
case "%user%":
{
var v = JsonConvert.DeserializeObject<User>(json);
d.Add(o.Key, v);
break;
}
case "%venue%":
{
var v = JsonConvert.DeserializeObject<Venue>(json);
d.Add(o.Key, v);
break;
}
case "%message%":
{
var v = JsonConvert.DeserializeObject<Message>(json);
d.Add(o.Key, v);
break;
}
}
}
答案 0 :(得分:2)
如果您使用的是Json.Net(又名Newtonsoft.Json),则可以创建自定义JsonConverter对象。该对象允许自定义解析json。所以,给出以下类
public class User
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Venue
{
public string Id { get; set; }
public string Address { get; set; }
}
public class Message
{
public string Text { get; set; }
[JsonProperty("fromId")]
public string FromId { get; set; }
}
您可以在另一个分配了JsonConverter
的类中包含它们[JsonConverter(typeof(PostJsonConverter))]
public class Post
{
public User User { get; set; }
public Venue Venue { get; set; }
public Message Message { get; set; }
}
JsonConvter类是一个抽象类,需要覆盖三种方法。您将要实现ReadJson方法。如果你不需要编写json,那么就不需要在WriteJson方法中做任何事情。
public class PostJsonConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
// not implemented
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
// it must be an object being passed in, if not something went wrong!
if (reader.TokenType != JsonToken.StartObject) throw new InvalidOperationException();
var postToken = JToken.ReadFrom(reader);
var userToken = postToken["%user%"];
var venueToken = postToken["%venue%"];
var messageToken = postToken["%message%"];
return new Post
{
User = userToken == null ? null : userToken.ToObject<User>(),
Venue = venueToken == null ? null : venueToken.ToObject<Venue>(),
Message = messageToken == null ? null : messageToken.ToObject<Message>(),
};
}
public override bool CanConvert(Type objectType)
{
return true;
}
}
将此转换为正常转换不需要额外的工作,因为我们已经为类提供了JsonConverterAttribute。
string myJson = "{\"%user%\":{\"id\" : 5, \"name\" : \"John\"}, \"%venue%\":{\"id\" : \"5f56de\", \"address\": \"Thomas at 68th Street\"}}";
Post post = JsonConvert.DeserializeObject<Post>(myJson);
答案 1 :(得分:0)
这是一个简洁的解决方案,使用我的小型JSON解析器库:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Venue
{
public int Id { get; set; }
public string Address { get; set; }
}
public class Message
{
public string Text { get; set; }
public int FromId { get; set; }
}
/* Deals with this SO question :
*
* http://stackoverflow.com/questions/19023696/deserialize-dictionarystring-t
*/
public static void SO_19023696()
{
Console.Clear();
Console.WriteLine("StackOverflow question 19023696 - Polymorphic, key-driven Test");
Console.WriteLine();
string myJson = @"
[
{
""%user%"" : { ""id"": 1, ""name"": ""Alex""} ,
""%venue%"" : { ""id"": 465, ""address"": ""Thomas at 68th Street"" },
""%message%"" : { ""text"": ""hello"", ""fromId"": 78 }
},
{
""%user%"" : { ""id"": 2, ""name"": ""Carl""} ,
""%message%"" : { ""text"": ""bye"", ""fromId"": 79 }
}
]";
Dictionary<string, object>[] parsed =
JSON.Map(null as Dictionary<string, object>[]).
FromJson
(
myJson,
JSON.Map(default(Dictionary<string, object>)).
Using // Deal with the main issue raised by the SO question:
(
(outer, type, value) =>
((outer.Hash != null) && outer.Hash.ContainsKey("Name") ? (Func<object>)
(() => new User { Id = (int)outer.Hash["Id"], Name = (string)outer.Hash["Name"] }) :
((outer.Hash != null) && outer.Hash.ContainsKey("Address") ? (Func<object>)
(() => new Venue { Id = (int)outer.Hash["Id"], Address = (string)outer.Hash["Address"] }) :
((outer.Hash != null) && outer.Hash.ContainsKey("Text") ? (Func<object>)
(() => new Message { FromId = (int)outer.Hash["FromId"], Text = (string)outer.Hash["Text"] }) :
null
)
)
)
),
Sample_Revivers.CamelCaseToPascalCase,
Sample_Revivers.DoubleToInteger
);
System.Diagnostics.Debug.Assert(parsed[0]["%user%"] is User);
System.Diagnostics.Debug.Assert(parsed[0]["%venue%"] is Venue);
System.Diagnostics.Debug.Assert(parsed[0]["%message%"] is Message);
System.Diagnostics.Debug.Assert(parsed[1]["%user%"] is User);
System.Diagnostics.Debug.Assert(parsed[1]["%message%"] is Message);
Console.Write("Passed - Press a key...");
Console.ReadKey();
}
可以在此处找到更多用例/示例,通用通用词典或匿名类型或POCO:
https://code.google.com/p/ysharp/source/browse/trunk/TestJSONParser/BasicTests.cs