Frage

Ich versuche, einige JSON Inhalt in C # zu analysieren. Für die einfacheren Fälle habe ich großen Erfolg mit JSON.NET und schätze den sauberen Ansatz der LINQ-Provider angeboten. Hier ist ein Beispiel, wo ich Informationen über eine Schicht in einer Karte bin Download und in einigen Eigenschaften einer Klasse Füllung genannt Schicht (suprisingly!):

        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"];

Sie können für diese Methode für Einzelheiten des JSON an dieser URL aussehen: http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/WaterTemplate/WaterDistributionNetwork/MapServer/1?f=json&pretty=true . Aber das Problem kommt, wenn ich die einzelnen Datenfelder assoziieren mit Kartenschichten in eine Datatable oder auch nur ein Wörterbuch Struktur drehen müssen. Das Problem ist, dass, anders als RSS oder andere konsistente Formate Feeds, um die Feldnamen und die Anzahl der Felder Änderungen von Karten-Layer-Schicht abzubilden. Hier ist ein Beispiel von mir eine Abfrage ausgeführt wird:

    [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);
    }

Der Code, der in layer.FindFeatureById laufen gelassen ist dies und schließt den Teil, wo ich stecken:

        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.

    }

Sie können die JSON sehen ausspucken durch diese URL besuchen (man beachte die Codierung, wenn Sie cut and paste): href = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/WaterTemplate/WaterDistributionNetwork/ MapServer / 1 / query? f = json & outfields = * & where = FacilityID% 3d'13141'

Also meine Frage (endlich!) Ist dies. Wie kann ich Zyklus durch die Sammlung von „Attribute“ in den „Eigenschaften“, um die aktuellen Feldwerte zu erhalten. Sie können sehen, dass ich herausgefunden habe, wie die Feldnamen aus dem fieldAliases zu bekommen, aber danach ist ich ratlos. Ich habe mit dem JsonReader auf eine Datei bastelt, der so aussieht, aber noch keine Freude:

{
  "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
    }
  }
]
}
War es hilfreich?

Lösung 2

Nun stellte sich heraus, das der beste Ansatz ein JsonTextReader zu verwenden war und rippen nur durch die Daten anstatt zu versuchen, LINQ zu verwenden. Es ist viel auf Einzug bekommt, das mich unglücklich macht, aber ich nehme an, dass eine unmittelbare Wirkung eine hierarchische Datenstruktur in erster Linie verwendet wird. Hier ist, wie die Liste der Zeilen drucken ( „Attribute“) und deren Name / Wert-Sammlungen:

        using (var file = File.OpenText(_fileWithGeom))
        {
            JsonReader reader = new JsonTextReader(file);

            while (reader.Read())
            {
                while (Convert.ToString(reader.Value) != "features")
                {
                    reader.Read();
                }

                Console.WriteLine("Found feature collections");

                // ignore stuff until we get to attribute array

                while (reader.Read())
                {
                    switch (Convert.ToString(reader.Value))
                    {
                        case "attributes":
                            Console.WriteLine("Found feature");
                            reader.Read(); // get pass attributes property

                            do
                            {
                                // As long as we're still in the attribute list...
                                if (reader.TokenType == JsonToken.PropertyName)
                                {
                                    var fieldName = Convert.ToString(reader.Value);
                                    reader.Read();
                                    Console.WriteLine("Name: {0}  Value: {1}", fieldName, reader.Value);
                                }

                                reader.Read();

                            } while (reader.TokenType != JsonToken.EndObject
                                     && Convert.ToString(reader.Value) != "attributes");
                            break;

                        case "geometry":
                            Console.WriteLine("Found geometry");
                            reader.Read();
                            break;
                    }
                }
            }
        }

Und dieses Mal bin ich auch Geometrie zu handhaben ist, so überprüfen Sie diese URL für die JSON, dass die obige Code-Analyse:

Andere Tipps

Für eine schnelle und schmutzige (nicht-LINQ) Art und Weise an den Attributen und Werten zu erhalten, gehen Sie folgendermaßen vor:

JObject jo = JObject.Parse(json);

foreach (JObject j in jo["features"])
{
  foreach (JProperty k in j["attributes"])
  {
    Console.WriteLine(k.Name + " = " + k.Value);
  }
}

Es ist nicht ideal, aber es funktioniert, wenn Sie die Feldnamen nicht wissen, die zurückkommen wird. Wenn ich einen besseren Weg finden, dies zu tun, ich werde es aktualisieren.

scroll top