使用Dynamic LINQ按一个或多个属性对JSON进行排序

时间:2014-10-02 23:36:02

标签: c# json linq sorting json.net

我有一些JSON需要在C#中排序。我尝试使用JObjectSystem.Linq.Dynamic列表进行排序,但我无法使用Newtonsoft.Json.Linq.JObject的实例进行排序。

这有效:

public class Row
{
    public String Column1 { get; set; }
    public Int32 Column2 { get; set; }
}

var rows = new List<Row>();

rows.Add(new Row { Column1 = "B", Column2 = 2 });
rows.Add(new Row { Column1 = "B", Column2 = 1 });
rows.Add(new Row { Column1 = "A", Column2 = 2 });
rows.Add(new Row { Column1 = "A", Column2 = 1 });

var sortedRows = rows.AsQueryable().OrderBy("Column1, Column2");

这不是:

var rows = new List<JObject>();

var row1 = new JObject();
row1["Column1"] = "B";
row1["Column2"] = 2;
rows.Add(row1);

var row2 = new JObject();
row2["Column1"] = "B";
row2["Column2"] = 1;
rows.Add(row2);

var row3 = new JObject();
row3["Column1"] = "A";
row3["Column2"] = 2;
rows.Add(row3);

var row4 = new JObject();
row4["Column1"] = "A";
row4["Column2"] = 1;
rows.Add(row4);

var sortedRows = rows.AsQueryable().OrderBy("Column1, Column2");
//System.Linq.Dynamic.ParseException : No property or field 'Column1' exists in type 'JObject'

如何在动态数量的属性上对JObject实例进行排序?

2 个答案:

答案 0 :(得分:2)

您可以使用System.Dynamic.Linq中的索引器语法:

var sortedRows = rows.AsQueryable().OrderBy(@"it[""Column1""], it[""Column2""]");

旧答案

您无法使用System.Linq.Dynamic执行此操作。要访问JObject的属性,您需要调用Property方法。但是,System.Linq.Dynamic不允许这样做。来自文档:

  

表达式语言将方法和构造函数的调用限制为可访问类型中声明为public的方法。

     
     

表达式语言定义以下基元类型

     

Object Boolean Char String SByte Byte Int16 UInt16 Int32 UInt32 Int64 UInt64 Decimal Single Double DateTime TimeSpan Guid

     

基本类型对应于.NET Framework基类库的System命名空间中类似命名的类型。表达式语言还定义了一组可访问类型,它们包含原始类型和System命名空间中的以下类型:

     

Math Convert

     

可访问类型是表达式中可以显式引用的唯一类型,表达式语言中的方法调用仅限于在可访问类型中声明的方法。

答案 1 :(得分:1)

您可以像这样实现自己的IComparer

public class MyJObjectComparer : IComparer<JObject>
{
    public int Compare(JObject a, JObject b)
    {
        if ((a["Column1"] == b["Column1"]) && a["Column2"] == b["Column2"]))
            return 0;

        if ((a["Column1"] < b["Columnq"]) || ((a["Column1"] == b["Column1"]) && (a["Column2"] < b["Column2"])))
            return -1;

        return 1;
    }
}

并像这样使用它:

var sortedRows = rows.AsQueryable().OrderBy(r => r, new MyJObjectComparer());