سؤال

وأنا محاولة لتحليل بعض المحتويات JSON في لC #. بالنسبة للحالات أبسط أواجه نجاحا كبيرا مع JSON.NET ونقدر حقا النهج نظيفة التي يقدمها مزود LINQ. وإليك مثال حيث أنا تحميل المعلومات حول طبقة في خريطة وملء بعض الخصائص على فئة تسمى طبقة (المدهش!):

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

ويمكنك إلقاء نظرة على هذا الرابط للاطلاع على تفاصيل JSON لهذا الأسلوب: <لأ href = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/WaterTemplate/WaterDistributionNetwork/MapServer/1؟f=json&pretty = صحيح "يختلط =" noreferrer نوفولو "> http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/WaterTemplate/WaterDistributionNetwork/MapServer/1؟f=json&pretty=true . ولكن المسألة تأتي عندما كنت في حاجة لتحويل حقول البيانات الفردية المنتسبين مع طبقات الخريطة إلى DataTable أو حتى مجرد هيكل القاموس. المشكلة هي أنه، على عكس آر إس إس أو تنسيقات متسقة أخرى، أسماء الحقول وعدد من التغييرات حقول من خريطة طبقة لطبقة الخريطة. وإليك مثالا لي تشغيل استعلام:

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

والتعليمات البرمجية التي يتم تشغيله في layer.FindFeatureById هو هذا ويتضمن الجزء حيث I تتعثر:

        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.

    }

ويمكنك مشاهدة JSON بصق من خلال زيارة هذا الرابط (لاحظ الترميز عند cut'n'paste): أ href = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/WaterTemplate/WaterDistributionNetwork/ MapServer / 1 / الاستعلام؟ و = سلمان وoutFields = * وحيث = FACILITYID٪ 3d'13141 '

وهكذا سؤالي (أخيرا!) هو هذا. كيف يمكنني التنقل بين مجموعة من "سمات" في "ملامح" للحصول على قيم الحقول الفعلية. يمكنك أن ترى أن لقد برزت كيفية الحصول على أسماء الحقول من fieldAliases، ولكن بعد ذلك أنا الحيرة. لقد تم ترقيع مع JsonReader على الملف الذي يبدو مثل هذا، ولكن لا يوجد حتى الآن الفرح:

{
  "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
    }
  }
]
}
هل كانت مفيدة؟

المحلول 2

وإضافة إلى أنه تبين أن أفضل طريقة لاستخدام JsonTextReader ومجرد مزق من خلال البيانات بدلا من محاولة استخدام LINQ. انها حصلت على الكثير على المسافة البادئة مما يجعلني سعيدة ولكن اعتقد ان هذا تأثير مباشر باستخدام بنية بيانات الهرمي في المقام الأول. وفيما يلي كيفية طباعة قائمة الصفوف ( "سمات") ومجموعات اسم / قيمتها:

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

وهذه المرة أواجه أيضا للتعامل مع الهندسة، لذلك تحقق من هذه URL للJSON أن رمز أعلاه هو تحليل:

<وأ href = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/WaterTemplate/WaterDistributionNetwork/MapServer/7/query؟where=OBJECTID٪3C10&returnGeometry=true&outSR=&outFields=" يختلط = "نوفولو noreferrer "> http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/WaterTemplate/WaterDistributionNetwork/MapServer/7/query؟where=OBJECTID٪3C10&returnGeometry=true&outSR=&outFields= * & F = pjson

نصائح أخرى

لوسيلة سريعة وقذرة (غير LINQ) للحصول على الصفات والقيم، جرب ما يلي:

JObject jo = JObject.Parse(json);

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

وانها ليست مثالية، ولكنه يعمل عندما كنت لا تعرف أسماء الحقول التي سوف يعود. إذا أجد طريقة أفضل للقيام بذلك، وسوف تحديثه.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top