用奇怪的格式解析json

时间:2017-10-30 20:18:26

标签: c# arrays json json.net

注意:如果您对此帖有更好的标题,请在评论中发帖。谢谢!

我正在使用一个返回json的api,它看起来像下面的代码片段。我对json非常熟悉,但我从未见过这样的结构。

resultFieldList fieldNames是固定的(下面有4个,但大约有20个)。 values数组是可变的,但每个fieldName的长度相同。

我在想我应该计算一个非空字段(OrderNumber),然后遍历每个fieldName,但这似乎效率低下。我想知道是否有更好的方法。这就是我获得记录数的方式:

string result = await response.Content.ReadAsStringAsync();
JObject m_json = (JObject)JsonConvert.DeserializeObject(result);
int m_count = m_json["resultFieldList"][3]["values"].Count();

这是json片段。

{
"collectionName": "Transactions",
"recordCount": 0,
"skippedRecordCount": 0,
"resultFieldList": 
  [{
    "fieldName": "SaleChannel",
    "analyticsDataType": "STRING",
    "values": ["Online", "Online", "Online", "Online", "Online", "Online", "Online", "Online", "Online", "Online", "Online", "Online", "Online", "Online", "Online", "Online", "Online", "Online", "Online", "Online"]
  },
  {
    "fieldName": "Quantity",
    "analyticsDataType": "INTEGER",
    "values": [1, 1, 1, 2, 1, 2, 1, 1, 1, 2, 2, 1, 2, 1, 1, 1, 2, 2, 1, 3]
  },
  {
    "fieldName": "Amount",
    "analyticsDataType": "CURRENCY",
    "values": ["25.00", "14.00", "14.00", "50.00", "14.00", "50.00", "14.00", "25.00", "18.00", "50.00", "36.00", "25.00", "50.00", "25.00", "14.00", "25.00", "50.00", "50.00", "25.00", "75.00"]
  }, 
  {
    "fieldName": "OrderNumber",
    "analyticsDataType": "STRING",
    "values": ["60937129", "60937129", "53221966", "14599547", "14599547", "10478305", "10478305", "95344699", "95344699", "83413371", "65720270", "43458148", "52500933", "32742144", "32742144", "89850688", "61514108", "11080559", "90497730", "22838522"]
  }]
}

准确的问题是是否可以创建一个新的数组或对象,其中每个值的索引被组合成给定此结构的新对象。例如,index [0]的值是" Online",1," 25.00"," 60937129"。所以它可能是一个新数组或一个全新的json对象。如果是这样,我将如何创建一个或另一个?输出将是这样的:

[ { "Online",1,"25.00","60937129" },{...} ]

或者

{"results": [ { "SaleChannel": "Online" , "Quantity": 1, "Amount": "25.00", "OrderNumber": "60937129" } , {...} ] 

ANSWER

使用@ JLRishe的答案我能够解析和使用用例数据 - 将api数据插入数据仓库。

enter image description here

2 个答案:

答案 0 :(得分:1)

修改:我相信在回答结束时我已经解决了你问题的要点。

您可能最好定义一个表示此结构的类型。由于values数组的内容具有不同的类型,因此您无法真正对它们进行假设,并且可能最安全地将它们视为object s:

public class MyClass
{
    public string collectionName { get; set; }

    public int recordCount { get; set; }

    public int skippedRecordCount { get; set; }

    public ResultField[] resultFieldList { get; set; }
}

public class ResultField
{
    public string fieldName { get; set; }

    public string analyticsDataType { get; set; }

    public object[] values { get; set; }
}

然后解析JSON只是一个问题:

string result = await response.Content.ReadAsStringAsync();
MyClass obj = JsonConvert.DeserializeObject<MyClass>(result);

实际使用数据时,您需要查看analyticsDataType中每个相应ResultField的值,并相应地转换values属性的内容。

或者,如果您不太关心将values视为原始类型,则可以将它们全部视为字符串,这将需要更少的类型检查。其他一切都会保持不变:

public string[] values { get; set; }

编辑现在你已经澄清了这个问题了,似乎这主要是关于将数据整理成更好的消费方式。

如果resultFieldList之外没有任何内容指示每个value数组中的值的数量,那么您基本上需要随意选择一个来获取计数:

int valueCount = obj.resultFieldList[0].values.Length;

然后,一旦你有了,你可以将这些值组合在一起:

// assuming OrderItem is a class you've defined with the needed 
// properties for one entry in an order
IEnumerable<OrderItem> items = Enumerable
    .Range(0, valueCount)
    .Select(i => new OrderItem {
         SaleChannel = Convert.ToString(obj.resultFieldList[0].values[i]),
         Quantity = Convert.ToInt32(obj.resultFieldList[1].values[i]),
         Amount = Convert.ToDecimal(obj.resultFieldList[2].values[i]),
         // etc...
    });

答案 1 :(得分:0)

使用Newtonsoft.Json并执行以下操作:

1)定义你的课程:

public class SomeObject
{
    public List<DynamicProperty> resultFieldList { get; set; }
}

public class DynamicProperty
{
    public string fieldName { get; set; }

    public string analyticsDataType { get; set; }

    public List<object> values { get; set; }
}

2)反序列化你的JSON:

var obj = JsonConvert.DeserializeObject<SomeObject>(json);
var t = obj.resultFieldList[3].values.Count();

如果您有任何疑问,请与我们联系。我使用你的JSON进行了测试,答案是20.此外,你可以使用Linq进行更复杂的分析。

编辑:基于正在扩展的问题。

3)创建一个Order类:

public class Order
{
    public string SaleChannel { get; set; }

    public int Quantity { get; set; }

    public Decimal Amount { get; set; }

    public string OrderNumber { get; set; }
}

4)生成基于json的可枚举和序列化:

var jsonValue = JsonConvert.SerializeObject(Enumerable
    .Range(0, obj.resultFieldList.Max(x => x.values.Count))
    .Select(i => new Order()
    {
        SaleChannel = obj.resultFieldList.FirstOrDefault(x => x.fieldName == nameof(Order.SaleChannel))?.values[i].ToString(),
        Quantity = Convert.ToInt32(obj.resultFieldList.FirstOrDefault(x => x.fieldName == nameof(Order.Quantity))?.values[i].ToString()),
        Amount = Convert.ToDecimal(obj.resultFieldList.FirstOrDefault(x => x.fieldName == nameof(Order.Amount))?.values[i].ToString()),
        OrderNumber = obj.resultFieldList.FirstOrDefault(x => x.fieldName == nameof(Order.OrderNumber))?.values[i].ToString()
    }));

〜干杯