我有一个奇怪的JSON,我需要反序列化。
它看起来像这样:
{
"Properties": [
{ "A": "aaa", "B": "bbb", "C": "ccc" },
{ "X": "xxx", "Y": "yyy" },
{ "many other": "items" }
],
"Products": [
{ "Id": 0, "PropertiesIndexes": [ 0, 1 ] },
{ "Id": 1, "PropertiesIndexes": [ 0, 1, 2 ] }
]
}
properties数组可以包含任意数量和名称的键,每个产品都通过索引访问属性数组。
我们需要将这些JSON文件存储在MongoDB中,因为它们可能非常庞大(我说的是一个文件的几百Mb)我需要拆分它们(Mongo有16Mb的限制)。因此,每个属性都是Mongo文档,每个产品都是Mongo文档 因为我不能按插入顺序获取属性,所以我们决定保存每个产品的所有属性。
以下是用于反序列化此数据的类(使用JSON.Net):
public class Entity {
public OrderedDictionary Properties { get; set; }
public IEnumerable<Product> Products { get; set; }
}
public class Product {
[JsonIgnore]
public Entity Entity { get; set; }
publid int Id { get; set; }
public int[] PropertiesIndexes { get; set; }
}
现在,我需要直接从产品中访问实际的属性数据,这样(假设的)生成的JSON就像这样:
{
"Products": [
{ "Id": 0,
"PropertiesData": [
{ "A": "aaa", "B": "bbb", "C": "ccc" },
{ "X": "xxx", "Y": "yyy" }
]
},
{ "Id": 1,
"PropertiesData": [
{ "A": "aaa", "B": "bbb", "C": "ccc" },
{ "X": "xxx", "Y": "yyy" },
{ "many other": "items" }
]
}
]
}
我天真的实现是这样的:
// in Product
[JsonIgnore]
public IDictionary<string, object> PropertiesData {
get {
if (this.Entity != null && this.Entity.Properties != null) {
var data = new Dictionary<string, object>();
for (int i = 0; i < this.PropertiesIndexes.Length; i++) {
data.Add(
this.Entity.Properties.Cast<DictionaryEntry>().ElementAt(this.PropertiesIndexes[i]).Key.ToString(),
this.Entity.Properties[this.PropertiesIndexes[i]]);
}
return data;
}
return new Dictionary<string, object>();
}
}
但它很慢(正如我所说,我有大量数据)并且非常难看。
当我们使用ExpandoObject
时,我有一个很好的,快速且内存有效的yeilding方法:
private IEnumerable<ExpandoObject> getPropertiesDataFromEntity() {
for (int i = 0; i < this.PropertiesIndexes.Count; i++) {
yield return this.Entity.Properties[this.PropertiesIndexes[i]];
}
}
但ExpandoObject
在我们的应用程序环境中有自己的问题:它们并不总是在Mongo中正确保存,并且在没有自定义序列化程序的情况下它们不会被WCF序列化。
答案 0 :(得分:1)
我已经编写了一些非常简单的东西,从源JSON到目标JSON 它包括4个非常简单的类。
前两个设计用于从源JSON反序列化:
public class Source
{
public Dictionary<string, string>[] Properties { get; set; }
public SourceProduct[] Products { get; set; }
}
public class SourceProduct
{
public int Id { get; set; }
public int[] PropertiesIndexes { get; set; }
}
第三类是目标产品:
public class Product
{
private List<Dictionary<string, string>> _propertiesData = new List<Dictionary<string, string>>();
public int Id { get; set; }
public List<Dictionary<string, string>> PropertiesData { get { return _propertiesData; } }
}
最后一个类是最终目标,我将数据从源转换为目标:
public class Target
{
private List<Product> _products = new List<Product>();
public IEnumerable<Product> Products { get { return _products; } }
public Target(Source source)
{
foreach(var sourceProduct in source.Products)
{
var product = new Product()
{
Id = sourceProduct.Id
};
foreach(var propertyIndex in sourceProduct.PropertiesIndexes)
{
product.PropertiesData.Add(source.Properties[propertyIndex]);
}
_products.Add(product);
}
}
}
使用这些类,您的客户端代码就变成了这样:
var targetJson = JsonConvert.SerializeObject
(
new Target(JsonConvert.DeserializeObject<Source>(sourceJson))
);