2012-09-17 13 views
8

Tengo una respuesta Json que recibo de una llamada API. Tiene varios niveles anidados como se muestra a continuación (este es un fragmento):Query JSON usando LINQ

"Items": [ 
    { 
    "Result": { 
     "Id": "191e24b8-887d-e111-96ec-000c29128cee", 
     "Name": "Name", 
     "StartDate": "2012-04-03T00:00:00+01:00", 
     "EndDate": null, 
     "Status": { 
     "Name": "Active", 
     "Value": 5 
     }, 
     "Client": { 
     "Id": "35ea10da-b8d5-4ef8-bf23-c829ae90fe60", 
     "Name": "client Name", 
     "AdditionalItems": {} 
     }, 
     "ServiceAgreement": { 
     "Id": "65216699-a409-44b0-8294-0e995eb05d9d", 
     "Name": "Name", 
     "AdditionalItems": { 
      "ScheduleBased": true, 
      "PayFrequency": { 
      "Id": "981acb72-8291-de11-98fa-005056c00008", 
      "Name": "Weekly", 
      "AdditionalItems": {} 
      }, 
      "PayCycle": [ 
      { 
       "Name": "Schedule Based", 
       "ScheduleBased": true, 
       "SelfBilling": false, 
       "Id": "a8a2ecc4-ff79-46da-a135-743b57808ec3", 
       "CreatedOn": "2011-09-16T23:32:19+01:00", 
       "CreatedBy": "System Administrator", 
       "ModifiedOn": "2011-09-16T23:32:19+01:00", 
       "ModifiedBy": "System Administrator", 
       "Archived": false 
      } 
      ] 
     } 
     }, 
} 
] 
... 

Lo que quiero hacer es retreive los datos desde el nodo PayCycle usando LINQ. por ejemplo, puedo conseguir los artículos con un valor de verdad usando Result.ServiceAgreement.AdditionalItems.SchedultedBased utilizando la siguiente LINQ en el controlador:

var result = from p in data["Data"]["Items"].Children() 
      where (bool)p["Result"]["ServiceAgreement"]["AdditionalItems"]["ScheduleBased"] == true 
      select new 
      { 
       Name = (string)p["Result"]["Client"]["Name"], 
       Id = (string)p["Result"]["Client"]["Id"] 
      }; 

Ahora tengo que conseguir Result.ServiceAgreement.AdditionalItems.Paycycle.ScheduleBased y SelfBilling propiedades. ¿Cómo hago esto si PayCycle también es una matriz, cómo obtengo los hijos como lo hice con Data.Items en el Linq anterior para que pueda tener el filtro cláusula where en ambos elementos?

Respuesta

12

Puede deserializar el JSON en un objeto dynamic, y luego usar LINQ a Objetos:

[TestMethod] 
    public void TestMethod1() 
    { 
     const string json = @"""Items"": [ 
{ 
""Result"": { 
    ""Id"": ""191e24b8-887d-e111-96ec-000c29128cee"", 
    ""Name"": ""Name"", 
    ""StartDate"": ""2012-04-03T00:00:00+01:00"", 
    ""EndDate"": null, 
    ""Status"": { 
    ""Name"": ""Active"", 
    ""Value"": 5 
    }, 
    ""Client"": { 
    ""Id"": ""35ea10da-b8d5-4ef8-bf23-c829ae90fe60"", 
    ""Name"": ""client Name"", 
    ""AdditionalItems"": {} 
    }, 
    ""ServiceAgreement"": { 
    ""Id"": ""65216699-a409-44b0-8294-0e995eb05d9d"", 
    ""Name"": ""Name"", 
    ""AdditionalItems"": { 
     ""ScheduleBased"": true, 
     ""PayFrequency"": { 
     ""Id"": ""981acb72-8291-de11-98fa-005056c00008"", 
     ""Name"": ""Weekly"", 
     ""AdditionalItems"": {} 
     }, 
     ""PayCycle"": [ 
     { 
      ""Name"": ""Schedule Based"", 
      ""ScheduleBased"": true, 
      ""SelfBilling"": false, 
      ""Id"": ""a8a2ecc4-ff79-46da-a135-743b57808ec3"", 
      ""CreatedOn"": ""2011-09-16T23:32:19+01:00"", 
      ""CreatedBy"": ""System Administrator"", 
      ""ModifiedOn"": ""2011-09-16T23:32:19+01:00"", 
      ""ModifiedBy"": ""System Administrator"", 
      ""Archived"": false 
     } 
     ] 
    } 
    } 
} 
} 
]"; 
     dynamic data = System.Web.Helpers.Json.Decode("{" + json + "}"); 

     var result = from i in (IEnumerable<dynamic>)data.Items 
        where i.Result.ServiceAgreement.AdditionalItems.ScheduleBased == true 
        select new 
          { 
           i.Result.Client.Name, 
           i.Result.Client.Id 
          }; 

     Assert.AreEqual(1, result.Count()); 
     Assert.AreEqual("client Name", result.First().Name); 
     Assert.AreEqual("35ea10da-b8d5-4ef8-bf23-c829ae90fe60", result.First().Id); 
    } 

Tenga en cuenta que he tenido que añadir corchetes {y} alrededor de su ejemplo de cadena JSON, o bien el .NET json parser no le gusta.

+0

He modificado ligeramente el mío ya que la colección PayCycle devolverá solo 1 artículo en la colección. Entonces, para que yo obtenga la propiedad SelfBilling, por ejemplo, hice lo siguiente en la cláusula where: where (bool) p ["Result"] ["ServiceAgreement"] ["AdditionalItems"] ["PayCycle"] [0] ["Auto facturación"] == falso. Esto me da el resultado que estoy buscando. – KDee

0

Para empezar, no estoy familiarizado con la escritura de LINQ/LAMBDA usando este formato ["algo"] ["cosa"]. Mi primer paso sería crear algunas clases/objetos para albergar los datos para facilitar la creación de cualquier código posteriormente.

p. Ej.

public class Result 
{ 
    public Guid Id { get; set; } 
    public string Name { get; set; }, 
    public DateTime StartDate { get; set; } 
    //you get the idea 
} 

Pero posiblemente intente lo siguiente?

var result = from p in data["Data"]["Items"].Children() 
       where (bool)p["Result"]["ServiceAgreement"]["AdditionalItems"]["ScheduleBased"] == true 
        && (p["Result"]["ServiceAgreement"]["AdditionalItems"]["PayCycle"]).Where(o => o.["ScheduleBased"] == true) 
       select new 
       { 
        Name = (string)p["Result"]["Client"]["Name"], 
        Id = (string)p["Result"]["Client"]["Id"] 
       };