Estoy intentando analizar el contenido JSON en C#. Para los casos más simples, estoy teniendo un gran éxito con JSON.NET y realmente aprecio el enfoque limpio que ofrece el proveedor de LINQ. He aquí un ejemplo en el que estoy descargando información sobre una capa en un mapa y rellenar algunas propiedades de una clase llamada capa (sorprendentemente!):LINQ y JSON.NET cuando los nombres de las propiedades varían
using (var client = new WebClient())
{
_content = client.DownloadString(_url.AbsoluteUri + OutputFormats.Json);
}
JObject json = JObject.Parse(_content);
IEnumerable<Field> fields = from f in json["fields"].Children()
select new Field(
(string)f["name"],
(string)f["alias"],
(EsriFieldType)Enum.Parse(typeof(EsriFieldType), (string)f["type"])
);
_fields = fields.ToList();
_displayFieldName = (string)json["displayField"];
Usted puede mirar en esta dirección URL para obtener información sobre el JSON para que método: http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/WaterTemplate/WaterDistributionNetwork/MapServer/1?f=json&pretty=true. Pero el problema surge cuando necesito convertir los campos de datos individuales asociados con capas de mapas en una DataTable o incluso solo en una estructura de diccionario. El problema es que, a diferencia de los canales RSS u otros formatos consistentes, los nombres de los campos y el número de campos cambian de capa de mapa a capa de mapa. He aquí un ejemplo de mi ejecución de una consulta:
[Test]
[Category(Online)]
public void Can_query_a_single_feature_by_id()
{
var layer = _map.LayersWithName(ObjectMother.LayerWithoutOID)[0];
layer.FindFeatureById("13141");
Assert.IsNotNull(layer.QueryResults);
}
El código que se ejecuta en layer.FindFeatureById es este e incluye la parte en que se queda bloqueado:
public void FindFeatureById(string id)
{
var queryThis = ObjectIdField() ?? DisplayField();
var queryUrl = string.Format("/query{0}&outFields=*&where=", OutputFormats.Json);
var whereClause = queryThis.DataType == typeof(string)
? string.Format("{0}='{1}'", queryThis.Name, id)
: string.Format("{0}={1}", queryThis.Name, id);
var where = queryUrl + HttpUtility.UrlEncode(whereClause);
var url = new Uri(_url.AbsoluteUri + where);
Debug.WriteLine(url.AbsoluteUri);
string result;
using (var client = new WebClient())
{
result = client.DownloadString(url);
}
JObject json = JObject.Parse(result);
IEnumerable<string> fields = from r in json["fieldAliases"].Children()
select ((JProperty)r).Name;
// Erm...not sure how to get this done.
// Basically need to populate class instances/rows with the
// values for each field where the list of fields is not
// known beforehand.
}
Se puede ver el JSON escupir a cabo por visitando esta URL (fíjate en la codificación cuando cortes): href = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/WaterTemplate/WaterDistributionNetwork/MapServer/1/query?f=json & outFields = * & donde = FACILITYID% 3d'13141 '
Entonces mi pregunta (¡por fin!) Es esto. ¿Cómo ciclo a través de la colección de "atributos" en las "características" para obtener los valores de campo reales. Puedes ver que he descubierto cómo obtener los nombres de campo de los fieldAliases, pero después de eso estoy perplejo. He estado jugando con la JsonReader en un archivo que tiene este aspecto, pero todavía no hay alegría:
{
"displayFieldName" : "FACILITYID",
"fieldAliases" : {
"FACILITYID" : "Facility Identifier",
"ACCOUNTID" : "Account Identifier",
"LOCATIONID" : "Location Identifier",
"CRITICAL" : "Critical Customer",
"ENABLED" : "Enabled",
"ACTIVEFLAG" : "Active Flag",
"OWNEDBY" : "Owned By",
"MAINTBY" : "Managed By"
},
"features" : [
{
"attributes" : {
"FACILITYID" : "3689",
"ACCOUNTID" : "12425",
"LOCATIONID" : "12425",
"CRITICAL" : 1,
"ENABLED" : 1,
"ACTIVEFLAG" : 1,
"OWNEDBY" : 1,
"MAINTBY" : 1
}
},
{
"attributes" : {
"FACILITYID" : "4222",
"ACCOUNTID" : "12958",
"LOCATIONID" : "12958",
"CRITICAL" : 1,
"ENABLED" : 1,
"ACTIVEFLAG" : 1,
"OWNEDBY" : 1,
"MAINTBY" : 1
}
}
]
}
bueno eso es bueno y simple. Gracias por la sugerencia. – Dylan