在C#中反序列化具有int作为键的JSON [英] Deserializing JSON that has an int as a key in C#
问题描述
我正在尝试反序列化此JSON
I am trying to deserialize this JSON
{
"39": {
"category": "Miscellaneous",
"country_whitelist": [],
"name": "domain.com",
"url_blacklist": [],
"country_blacklist": [],
"url_whitelist": [
"domain.com"
],
"deals": {
"425215": {
"status": "Ok",
"type": "",
"code": "CODE",
"end_date": "2014-03-01 04:00:00",
"title": "RandomTitle",
"url": "http://domain.com/foo",
"text": "Text Text Text",
"long_title": "Longer Text"
},
"425216": {
"status": "Ok",
"type": "",
"code": "CODE2",
"end_date": "2014-03-01 04:00:00",
"title": "RandomTitle2",
"url": "http://domain.com/bar",
"text": "Text Text Text",
"long_title": "Longer Text"
}
},
"88x31": "http://someimage/88x31.png",
"subcategory": "Other"
},
"40": {
"category": "Miscellaneous",
"country_whitelist": [],
"name": "domain.com",
"url_blacklist": [],
"country_blacklist": [],
"url_whitelist": [
"domain.com"
],
"products": {
"425215": {
"status": "Ok",
"type": "",
"code": "CODE",
"end_date": "2014-03-01 04:00:00",
"title": "RandomTitle",
"url": "http://domain.com/foo",
"text": "Text Text Text",
"long_title": "Longer Text"
},
"425216": {
"status": "Ok",
"type": "",
"code": "CODE2",
"end_date": "2014-03-01 04:00:00",
"title": "RandomTitle2",
"url": "http://domain.com/bar",
"text": "Text Text Text",
"long_title": "Longer Text"
}
},
"88x31": "http://someimage/88x31.png",
"subcategory": "Other"
}
}
我尝试使用Json.NET,并尝试使用ServiceStack的反序列化器,但似乎无法获得此JSON的任何类型的表示形式.
I tried using Json.NET and I tried using ServiceStack's deserializer but I can't seem to get any type of representation for this JSON.
我认为阻止我的主要因素是密钥是Int,但是我无法控制收到的JSON.
The main thing that is blocking me I believe is that the keys are Int but I don't have control on the JSON I receive.
这是我建立的C#类
public class product
{
public string status { get; set; }
public string type { get; set; }
public string code { get; set; }
public string end_date { get; set; }
public string title { get; set; }
public string url { get; set; }
public string text { get; set; }
public string long_title { get; set; }
}
public class Merchant
{
public string category { get; set; }
public List<string> country_whitelist { get; set; }
public string name { get; set; }
public List<string> url_blacklist { get; set; }
public List<string> country_blacklist { get; set; }
public List<string> url_whitelist { get; set; }
public List<product> products { get; set; }
public string subcategory { get; set; }
}
public class Data
{
public Dictionary<int, Merchant> MainMerchants { get; set; }
}
我更喜欢使用ServiceStack,但其他任何可用的反序列化器都将很好
I prefer using ServiceStack but any other deserializer that works will be great
var data = client.Get(json);
var data = client.Get(json);
推荐答案
获取正确映射的数据类型:
可以反序列化JSON.如正确识别,则可以反序列化为Dictionary<int, Merchant>
.
但是您需要将Merchant
类中的products
定义更改为Dictionary<int, Product>
.这里需要一个字典来处理您的数字键. List<Product>
无法正常工作.
But you will need to change your definition of products
in the Merchant
class to be a Dictionary<int, Product>
. It needs to be a dictionary here to handle your numeric key. List<Product>
won't work.
还可以使用DataMember(Name = '88x31')
映射将其映射到c#喜欢的东西,例如image88x31
,以处理88x31
属性.不幸的是,这确实意味着您的DTO属性将变为选择加入状态,因此您将需要装饰所有成员. 添加using System.Runtime.Serialization;
Also to handle the 88x31
property you can use a DataMember(Name = '88x31')
mapping to map it to something c# likes, like image88x31
. Unfortunately this does mean your DTO properties become opt-in so you will then need to decorate all members. Add using System.Runtime.Serialization;
一旦进行了以下更改:
// Note I capitalized Product
public class Product
{
public string status { get; set; }
public string type { get; set; }
public string code { get; set; }
public string end_date { get; set; }
public string title { get; set; }
public string url { get; set; }
public string text { get; set; }
public string long_title { get; set; }
}
/*
* Use DataMember to map the keys starting with numbers to an alternative c# compatible name.
* Unfortunately this requires properties to opt in to the data contract.
*/
[DataContract]
public class Merchant
{
[DataMember]
public string category { get; set; }
[DataMember]
public List<string> country_whitelist { get; set; }
[DataMember]
public string name { get; set; }
[DataMember]
public List<string> url_blacklist { get; set; }
[DataMember]
public List<string> country_blacklist { get; set; }
[DataMember]
public List<string> url_whitelist { get; set; }
[DataMember]
public Dictionary<int, Product> products { get; set; }
[DataMember]
public string sub_category { get; set; }
// This maps the 88x31 key to a c# appropriate name
[DataMember(Name = "88x31")]
public string image88x31 { get; set; }
}
然后您将可以反序列化为Dictionary<int, Merchant>
,而不会出现任何问题.
Then you will be able to deserialize into Dictionary<int, Merchant>
without any issues.
JsonSerializer.DeserializeFromString<Dictionary<int, Merchant>>("YOUR JSON STRING");
在ServiceStack服务中使用:
如果希望能够将此请求直接发送到ServiceStack服务,则可以使用RequestBinder
来反序列化为这种复杂类型.有了这项服务:
Using in a ServiceStack Service:
If you want to be able to send this request directly to a ServiceStack service, then you can use a RequestBinder
to deserialize into this complex type. Given this service:
请求DTO:
[Route("/Merchants", "POST")]
public class MerchantsRequest
{
public Dictionary<int, Merchant> MainMerchants { get; set; }
}
简单操作方法:
public class MerchantsService : Service
{
public void Post(MerchantsRequest request)
{
var merchant39 = request.MainMerchants.First(p=>p.Key == 39).Value;
Console.WriteLine("Name: {0}\nImage: {1}\nProduct Count: {2}", merchant39.name, merchant39.image88x31, merchant39.products.Count);
var merchant40 = request.MainMerchants.First(p=>p.Key == 40).Value;
Console.WriteLine("Name: {0}\nImage: {1}\nProduct Count: {2}", merchant40.name, merchant40.image88x31, merchant40.products.Count);
}
}
AppHost配置:
AppHost Configuration:
在您的AppHost
Configure
方法中,您需要将绑定器添加到请求类型.即typeof(MerchantsRequest)
这样:
In your AppHost
Configure
method you would need to add a binder to the request type. i.e. typeof(MerchantsRequest)
like so:
public override void Configure(Funq.Container container)
{
Func<IRequest, object> merchantsRequestBinder = delegate(IRequest request) {
var json = WebUtility.HtmlDecode( request.GetRawBody() );
return new MerchantsRequest { MainMerchants = JsonSerializer.DeserializeFromString<Dictionary<int, Merchant>>(json) };
};
RequestBinders.Add(typeof(MerchantsRequest), merchantsRequestBinder);
...
}
此资料夹方法会将您发送的json转换为MerchantsRequest
.然后,您可以像常规ServiceStack请求一样使用它.
This binder method will convert the json you are sending into a MerchantsRequest
. Then you can use it like a regular ServiceStack request.
控制台应用程序的一个完全正常的示例,演示了将复杂的JSON转换为服务请求的情况.
A fully working example of console application, demonstrating the conversion of the complex JSON to a service request.
注意:我在您的JSON中注意到,您在一个对象上具有属性deals
,在另一个对象上具有products
属性,我认为这是一个错字,因为您没有相应的属性在deals
的类中.
Note: I notice in your JSON that you have property deals
on one object, and products
on another, I assumed this was a typo, as you don't have a corresponding property on in the class for deals
.
这篇关于在C#中反序列化具有int作为键的JSON的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!