如何在C#中过滤JSON数组

时间:2014-05-16 14:55:16

标签: c# json filter json.net

我花了很多时间为我的问题找到解决方案。

在这个例子中,我在SetNavRecords数组中有2条记录。 第一个是" Artikelnummer" :" 21700" ,第二个是" Artikelnummer" :" 21701"

每条记录都有一个数组" OfflineVerkaufspreis"。

重要的是我的领域" Location_Code" in" OfflineVerkaufspreis" 我只需要一个过滤的位置代码的孔信息。

如何为一个位置代码选择数据,例如" MH"?

我使用C#和Newtonsoft类进行JSON解析。

我尝试过使用LINQ的某些版本,但没有成功。

{ "SetNavRecords" : [ { "Artikelbeschreibung" : "Trikot \"Home\" 2012/2013",
    "Artikelbeschreibung2" : "weiß",
    "Artikelnummer" : "21700",
    "Artikelrabattgruppe" : "MERCH",
    "Gutschein" : false,
    "MwStProduktgruppe" : "VOLLNEU",
    "OfflineVerkaufspreis" : [ { "Allow_Line_Discount" : true,
          "Date" : "2014-05-16T00:00:00",
          "Item_No" : "21700",
          "Location_Code" : "BP",
          "Unit_Price" : 5.0
        },
        { "Allow_Line_Discount" : true,
          "Date" : "2014-05-16T00:00:00",
          "Item_No" : "21700",
          "Location_Code" : "MH",
          "Unit_Price" : 5.0
        },
        { "Allow_Line_Discount" : true,              
          "Date" : "2014-05-16T00:00:00",
          "Item_No" : "21700",
          "Location_Code" : "RY",
          "Unit_Price" : 5.0
        }
      ]
  },
  { "Artikelbeschreibung" : "Autogrammtrikot 2012/2013",
    "Artikelbeschreibung2" : "weiß",
    "Artikelnummer" : "21701",
    "Artikelrabattgruppe" : "MERCH",
    "Gutschein" : false,
    "MwStProduktgruppe" : "VOLLNEU",
    "OfflineVerkaufspreis" : [ { "Allow_Line_Discount" : false,
          "Date" : "2014-05-16T00:00:00",
          "Item_No" : "21701",
          "Location_Code" : "BP",
          "Unit_Price" : 69.99
        },
        { "Allow_Line_Discount" : false,
          "Date" : "2014-05-16T00:00:00",
          "Item_No" : "21701",
          "Location_Code" : "MH",
          "Unit_Price" : 69.99
        },
        { "Allow_Line_Discount" : false,
          "Date" : "2014-05-16T00:00:00",
          "Item_No" : "21701",
          "Location_Code" : "RY",
          "Unit_Price" : 69.99
        }
      ]
  }

] }

这是我的问题:

var tmpResult = JObject.Parse(File.ReadAllText(FileName));
var resultObject = tmpResult["SetNavRecords"]
      .Values("OfflineVerkaufspreis")
      .Values<JObject>()                                   
      .Where(n => n["Location_Code"].Value<string>() == "MH"); 

过滤器工作正常,但tmpResult中的数据不完整。我只获得&#34; OfflineVerkaufspreis&#34;中的数据。我也需要根数据。

有人有想法吗?

谢谢!

3 个答案:

答案 0 :(得分:3)

通过切换到json到对象的序列化,这感觉就像一件可以变得更容易的工作。要将json反序列化为可以使用的对象:

RootObject obj = JsonConvert.DeserializeObject<RootObject>(jsonString);

同样,你可以使用:

将你的对象变回json
string jsonString = JsonConvert.SerializeObject(RootObject);

基于您在问题中提供的json的对象结构是这样的:

public class OfflineVerkaufsprei
{
    public bool Allow_Line_Discount { get; set; }
    public string Date { get; set; }
    public string Item_No { get; set; }
    public string Location_Code { get; set; }
    public double Unit_Price { get; set; }
}

public class SetNavRecord
{
    public string Artikelbeschreibung { get; set; }
    public string Artikelbeschreibung2 { get; set; }
    public string Artikelnummer { get; set; }
    public string Artikelrabattgruppe { get; set; }
    public bool Gutschein { get; set; }
    public string MwStProduktgruppe { get; set; }
    public List<OfflineVerkaufsprei> OfflineVerkaufspreis { get; set; }
}

public class RootObject
{
    public List<SetNavRecord> SetNavRecords { get; set; }
}
然后,您可以通过以下方式轻松迭代您的对象:

for each(SetNavRecord i in obj.SetNavRecords)
{
    // do something to the record
}

答案 1 :(得分:2)

var tmpResult = JObject.Parse(File.ReadAllText(FileName));
var resultObject = tmpResult["SetNavRecords"].Values("OfflineVerkaufspreis").Values<JObject>()                                   
            .Where(n => n["Location_Code"].Value<string>() == "MH");   

此代码将导航至OfflineVerkaufspreis.Values,然后对其进行过滤。 但是(我猜)您想要选择与您的Where子句匹配的位置,然后选择父详细信息。

您可以使用Select选择您真正感兴趣的所有信息。

var resultObject = tmpResult["SetNavRecords"].Values("OfflineVerkaufspreis").Values<JObject>()
           .Where(n => n["Location_Code"].Value<string>() == "MH")
           .Select(n => new { Location = n, Context = n.Parent }).ToArray();

当然,您可以只选择您真正需要的信息而不是整个父母。

为了使这段代码更具可读性,我建议创建一些与JSon输入匹配的类,以便将JSon映射到这个对象图。它将使您的Linq更容易编写,阅读和理解。

<强>更新 建议在评论中使用:.Where(n => n["OfflineVerkaufspreis"]["Location_Code"] ...。这种方法的问题是,最后您不知道哪个OfflineVerkaufspreis实际上与您的where子句匹配...

答案 2 :(得分:1)

我会用名称SetNavRecords和OfflineVerkaufspreis创建类。然后我会使用命名空间 System.Web.Script.Serialization.JavaScriptSerializer 中的 JavaScriptSerializer 对其进行反序列化。

代码就像这样 -

JavaScriptSerializer.Deserialize(String, Type);

然后我可以像简单的通用收集一样操作它,例如。列表。

希望这对你有所帮助。