Парсинг JSON с использованием Json.net


Я пытаюсь разобрать некоторые JSON с помощью JSon.Net библиотека. Документация кажется немного скудной, и я смущен тем, как выполнить то, что мне нужно. Вот формат для JSON, который мне нужно разобрать.

{
    "displayFieldName" : "OBJECT_NAME", 
    "fieldAliases" : {
        "OBJECT_NAME" : "OBJECT_NAME", 
        "OBJECT_TYPE" : "OBJECT_TYPE"
    }, 
    "positionType" : "point", 
    "reference" : {
        "id" : 1111
    }, 
    "objects" : [ {
        "attributes" : {
            "OBJECT_NAME" : "test name", 
            "OBJECT_TYPE" : "test type"
        }, 
        "position" : {
            "x" : 5, 
            "y" : 7
        }
    } ]
}

единственные данные, которые мне действительно нужны от этого, - это материал в массиве объектов. Возможно ли для меня проанализировать это с помощью чего-то вроде JSonTextReader и просто вытащить то, что я хочу, например OBJECT_TYPE и позицию x и y? Я не могу кажется, чтобы получить JSonTextReader работать так, как я хочу, и я нахожу мало примеров использования для него.

Кажется, что сначала сериализация, а затем использование LINQ с моим объектом было бы идеальным, и каждый пример, который я нахожу, сначала обсуждает сериализацию JSON, но я не уверен, как бы я построил объект для этой структуры. В частности, массив объектов, который должен быть чем-то вроде списка пар объектов атрибутов и позиций. Я понятия не имею, как бы я закодировал свой объект так JSon.Net будет знать, как сериализовать это.

Я думал, что могу написать свой собственный простой парсер, чтобы просто вытащить все, что мне нужно, в объект атрибутов, который я создал, но мне мало повезло.

надеюсь, это все имеет смысл, какие-то идеи?

5 111

5 ответов:

Я не знаю о JSON.NET, но он отлично работает с JavaScriptSerializer С System.Web.Extensions.dll (.NET 3.5 С ПАКЕТОМ ОБНОВЛЕНИЯ 1):

using System.Collections.Generic;
using System.Web.Script.Serialization;
public class NameTypePair
{
    public string OBJECT_NAME { get; set; }
    public string OBJECT_TYPE { get; set; }
}
public enum PositionType { none, point }
public class Ref
{
    public int id { get; set; }
}
public class SubObject
{
    public NameTypePair attributes { get; set; }
    public Position position { get; set; }
}
public class Position
{
    public int x { get; set; }
    public int y { get; set; }
}
public class Foo
{
    public Foo() { objects = new List<SubObject>(); }
    public string displayFieldName { get; set; }
    public NameTypePair fieldAliases { get; set; }
    public PositionType positionType { get; set; }
    public Ref reference { get; set; }
    public List<SubObject> objects { get; set; }
}
static class Program
{

    const string json = @"{
  ""displayFieldName"" : ""OBJECT_NAME"", 
  ""fieldAliases"" : {
    ""OBJECT_NAME"" : ""OBJECT_NAME"", 
    ""OBJECT_TYPE"" : ""OBJECT_TYPE""
  }, 
  ""positionType"" : ""point"", 
  ""reference"" : {
    ""id"" : 1111
  }, 
  ""objects"" : [
    {
      ""attributes"" : {
        ""OBJECT_NAME"" : ""test name"", 
        ""OBJECT_TYPE"" : ""test type""
      }, 
      ""position"" : 
      {
        ""x"" : 5, 
        ""y"" : 7
      }
    }
  ]
}";


    static void Main()
    {
        JavaScriptSerializer ser = new JavaScriptSerializer();
        Foo foo = ser.Deserialize<Foo>(json);
    }


}

Edit:

Json.NET работает с использованием тех же JSON и классов.

Foo foo = JsonConvert.DeserializeObject<Foo>(json);

ссылки: сериализация и десериализация JSON с помощью Json.NET

Edit: спасибо Марк, прочитайте о проблеме struct vs class, и вы правы, спасибо!

Я склонен использовать следующий метод для выполнения того, что вы описываете, используя статический метод JSon.Net:

MyObject deserializedObject = JsonConvert.DeserializeObject<MyObject>(json);

ссылки: сериализация и десериализация JSON с помощью Json.NET

для списка объектов я могу предложить использовать общие списки, сделанные из вашего собственного небольшого класса, содержащего attributes и position класса. Вы можете использовать Point struct in System.Drawing (System.Drawing.Point или System.Drawing.PointF для чисел с плавающей запятой) для вас X и Y.

после создания объекта много легче получить данные, которые вы ищете, по сравнению с разбором текста, на который вы иначе смотрите.

/*
     * This method takes in JSON in the form returned by javascript's
     * JSON.stringify(Object) and returns a string->string dictionary.
     * This method may be of use when the format of the json is unknown.
     * You can modify the delimiters, etc pretty easily in the source
     * (sorry I didn't abstract it--I have a very specific use).
     */ 
    public static Dictionary<string, string> jsonParse(string rawjson)
    {
        Dictionary<string, string> outdict = new Dictionary<string, string>();
        StringBuilder keybufferbuilder = new StringBuilder();
        StringBuilder valuebufferbuilder = new StringBuilder();
        StringReader bufferreader = new StringReader(rawjson);

        int s = 0;
        bool reading = false;
        bool inside_string = false;
        bool reading_value = false;
        //break at end (returns -1)
        while (s >= 0)
        {
            s = bufferreader.Read();
            //opening of json
            if (!reading)
            {
                if ((char)s == '{' && !inside_string && !reading) reading = true;
                continue;
            }
            else
            {
                //if we find a quote and we are not yet inside a string, advance and get inside
                if (!inside_string)
                {
                    //read past the quote
                    if ((char)s == '\"') inside_string = true;
                    continue;
                }
                if (inside_string)
                {
                    //if we reached the end of the string
                    if ((char)s == '\"')
                    {
                        inside_string = false;
                        s = bufferreader.Read(); //advance pointer
                        if ((char)s == ':')
                        {
                            reading_value = true;
                            continue;
                        }
                        if (reading_value && (char)s == ',')
                        {
                            //we know we just ended the line, so put itin our dictionary
                            if (!outdict.ContainsKey(keybufferbuilder.ToString())) outdict.Add(keybufferbuilder.ToString(), valuebufferbuilder.ToString());
                            //and clear the buffers
                            keybufferbuilder.Clear();
                            valuebufferbuilder.Clear();
                            reading_value = false;
                        }
                        if (reading_value && (char)s == '}')
                        {
                            //we know we just ended the line, so put itin our dictionary
                            if (!outdict.ContainsKey(keybufferbuilder.ToString())) outdict.Add(keybufferbuilder.ToString(), valuebufferbuilder.ToString());
                            //and clear the buffers
                            keybufferbuilder.Clear();
                            valuebufferbuilder.Clear();
                            reading_value = false;
                            reading = false;
                            break;
                        }
                    }
                    else
                    {
                        if (reading_value)
                        {
                            valuebufferbuilder.Append((char)s);
                            continue;
                        }
                        else
                        {
                            keybufferbuilder.Append((char)s);
                            continue;
                        }
                    }
                }
                else
                {
                    switch ((char)s)
                    {
                        case ':':
                            reading_value = true;
                            break;
                        default:
                            if (reading_value)
                            {
                                valuebufferbuilder.Append((char)s);
                            }
                            else
                            {
                                keybufferbuilder.Append((char)s);
                            }
                            break;
                    }
                }
            }
        }
        return outdict;
    }

(этот вопрос возник высоко на результат поисковой системы, но я в конечном итоге с помощью другого подхода. Добавление ответа на этот старый вопрос в случае, если другие люди с подобными вопросами читают это)

вы можете решить эту проблему с помощью Json.Net и сделать метод расширения для обработки элементов, которые вы хотите цикл:

public static Tuple<string, int, int> ToTuple(this JToken token)
{
    var type = token["attributes"]["OBJECT_TYPE"].ToString();
    var x = token["position"]["x"].Value<int>();
    var y = token["position"]["y"].Value<int>();
    return new Tuple<string, int, int>(type, x, y);
}

а затем получить доступ к данным следующим образом: (сценарий: запись в консоль):

var tuples = JObject.Parse(myJsonString)["objects"].Select(item => item.ToTuple()).ToList();
tuples.ForEach(t => Console.WriteLine("{0}: ({1},{2})", t.Item1, t.Item2, t.Item3));

использовать JSON класса, а затем вызвать