web-dev-qa-db-ja.com

Json.netを使用したJSONの解析

JSon.Netライブラリを使用してJSONを解析しようとしています。ドキュメントは少しまばらで、必要なことをどのように達成するかについて混乱しています。解析する必要がある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がそれをシリアル化する方法を知っているので、私は自分のオブジェクトをどのようにコーディングするのか分かりません。

私は自分が作成した属性オブジェクトに必要なものをすべて引き出すために自分の簡単なパーサーを書くことができると思っていましたが、私はほとんど運がありません。

うまくいけば、これがすべて理にかなっていると思いますか?

111
Carter

JSON.NETについては知りませんが、System.Web.Extensions.dll(.NET 3.5 SP1)のJavaScriptSerializerでうまく機能します。

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


}

編集:

Json.NETは、同じJSONとクラスを使用して動作します。

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

リンク: Json.NETでJSONをシリアル化および逆シリアル化します

129
Marc Gravell

編集:マーク、クラス対クラスの問題を読んでくれてありがとう、あなたは正しい、ありがとう!

JSon.Netの静的メソッドを使用して、説明することを行うために次のメソッドを使用する傾向があります。

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

リンク: Json.NETでJSONをシリアル化および逆シリアル化します

オブジェクトリストについては、attributesおよびpositionクラスを含む独自の小さなクラスで作成された汎用リストを使用することをお勧めします。 XおよびYに対して、System.Drawing(浮動小数点数の場合はSystem.Drawing.PointまたはSystem.Drawing.PointF)でPoint構造体を使用できます。

オブジェクトの作成後、muchで、目的のデータを取得するのが簡単になります。

10
jarrodn

(この質問は検索エンジンの結果で高くなりましたが、私は別のアプローチを使用することになりました。同様の質問を持つ他の人がこれを読む場合に備えて、この古い質問に答えを追加します)

これを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));
3
PMBjornerud
/*
     * 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;
    }
2
Sam Grondahl

JSONクラスを使用してから、GetData()関数を呼び出します。

/// <summary>
/// This class encodes and decodes JSON strings.
/// Spec. details, see http://www.json.org/
///
/// JSON uses Arrays and Objects. These correspond here to the datatypes ArrayList and Hashtable.
/// All numbers are parsed to doubles.
/// </summary>
    using System;
    using System.Collections;
    using System.Globalization;
    using System.Text;

public class JSON
{
    public const int TOKEN_NONE = 0;
    public const int TOKEN_CURLY_OPEN = 1;
    public const int TOKEN_CURLY_CLOSE = 2;
    public const int TOKEN_SQUARED_OPEN = 3;
    public const int TOKEN_SQUARED_CLOSE = 4;
    public const int TOKEN_COLON = 5;
    public const int TOKEN_COMMA = 6;
    public const int TOKEN_STRING = 7;
    public const int TOKEN_NUMBER = 8;
    public const int TOKEN_TRUE = 9;
    public const int TOKEN_FALSE = 10;
    public const int TOKEN_NULL = 11;

    private const int BUILDER_CAPACITY = 2000;

    /// <summary>
    /// Parses the string json into a value
    /// </summary>
    /// <param name="json">A JSON string.</param>
    /// <returns>An ArrayList, a Hashtable, a double, a string, null, true, or false</returns>
    public static object JsonDecode(string json)
    {
        bool success = true;

        return JsonDecode(json, ref success);
    }

    /// <summary>
    /// Parses the string json into a value; and fills 'success' with the successfullness of the parse.
    /// </summary>
    /// <param name="json">A JSON string.</param>
    /// <param name="success">Successful parse?</param>
    /// <returns>An ArrayList, a Hashtable, a double, a string, null, true, or false</returns>
    public static object JsonDecode(string json, ref bool success)
    {
        success = true;
        if (json != null) {
            char[] charArray = json.ToCharArray();
            int index = 0;
            object value = ParseValue(charArray, ref index, ref success);
            return value;
        } else {
            return null;
        }
    }

    /// <summary>
    /// Converts a Hashtable / ArrayList object into a JSON string
    /// </summary>
    /// <param name="json">A Hashtable / ArrayList</param>
    /// <returns>A JSON encoded string, or null if object 'json' is not serializable</returns>
    public static string JsonEncode(object json)
    {
        StringBuilder builder = new StringBuilder(BUILDER_CAPACITY);
        bool success = SerializeValue(json, builder);
        return (success ? builder.ToString() : null);
    }

    protected static Hashtable ParseObject(char[] json, ref int index, ref bool success)
    {
        Hashtable table = new Hashtable();
        int token;

        // {
        NextToken(json, ref index);

        bool done = false;
        while (!done) {
            token = LookAhead(json, index);
            if (token == JSON.TOKEN_NONE) {
                success = false;
                return null;
            } else if (token == JSON.TOKEN_COMMA) {
                NextToken(json, ref index);
            } else if (token == JSON.TOKEN_CURLY_CLOSE) {
                NextToken(json, ref index);
                return table;
            } else {

                // name
                string name = ParseString(json, ref index, ref success);
                if (!success) {
                    success = false;
                    return null;
                }

                // :
                token = NextToken(json, ref index);
                if (token != JSON.TOKEN_COLON) {
                    success = false;
                    return null;
                }

                // value
                object value = ParseValue(json, ref index, ref success);
                if (!success) {
                    success = false;
                    return null;
                }

                table[name] = value;
            }
        }

        return table;
    }

    protected static ArrayList ParseArray(char[] json, ref int index, ref bool success)
    {
        ArrayList array = new ArrayList();

        // [
        NextToken(json, ref index);

        bool done = false;
        while (!done) {
            int token = LookAhead(json, index);
            if (token == JSON.TOKEN_NONE) {
                success = false;
                return null;
            } else if (token == JSON.TOKEN_COMMA) {
                NextToken(json, ref index);
            } else if (token == JSON.TOKEN_SQUARED_CLOSE) {
                NextToken(json, ref index);
                break;
            } else {
                object value = ParseValue(json, ref index, ref success);
                if (!success) {
                    return null;
                }

                array.Add(value);
            }
        }

        return array;
    }

    protected static object ParseValue(char[] json, ref int index, ref bool success)
    {
        switch (LookAhead(json, index)) {
            case JSON.TOKEN_STRING:
                return ParseString(json, ref index, ref success);
            case JSON.TOKEN_NUMBER:
                return ParseNumber(json, ref index, ref success);
            case JSON.TOKEN_CURLY_OPEN:
                return ParseObject(json, ref index, ref success);
            case JSON.TOKEN_SQUARED_OPEN:
                return ParseArray(json, ref index, ref success);
            case JSON.TOKEN_TRUE:
                NextToken(json, ref index);
                return true;
            case JSON.TOKEN_FALSE:
                NextToken(json, ref index);
                return false;
            case JSON.TOKEN_NULL:
                NextToken(json, ref index);
                return null;
            case JSON.TOKEN_NONE:
                break;
        }

        success = false;
        return null;
    }

    protected static string ParseString(char[] json, ref int index, ref bool success)
    {
        StringBuilder s = new StringBuilder(BUILDER_CAPACITY);
        char c;

        EatWhitespace(json, ref index);

        // "
        c = json[index++];

        bool complete = false;
        while (!complete) {

            if (index == json.Length) {
                break;
            }

            c = json[index++];
            if (c == '"') {
                complete = true;
                break;
            } else if (c == '\\') {

                if (index == json.Length) {
                    break;
                }
                c = json[index++];
                if (c == '"') {
                    s.Append('"');
                } else if (c == '\\') {
                    s.Append('\\');
                } else if (c == '/') {
                    s.Append('/');
                } else if (c == 'b') {
                    s.Append('\b');
                } else if (c == 'f') {
                    s.Append('\f');
                } else if (c == 'n') {
                    s.Append('\n');
                } else if (c == 'r') {
                    s.Append('\r');
                } else if (c == 't') {
                    s.Append('\t');
                } else if (c == 'u') {
                    int remainingLength = json.Length - index;
                    if (remainingLength >= 4) {
                        // parse the 32 bit hex into an integer codepoint
                        uint codePoint;
                        if (!(success = UInt32.TryParse(new string(json, index, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out codePoint))) {
                            return "";
                        }
                        // convert the integer codepoint to a unicode char and add to string
                        s.Append(Char.ConvertFromUtf32((int)codePoint));
                        // skip 4 chars
                        index += 4;
                    } else {
                        break;
                    }
                }

            } else {
                s.Append(c);
            }

        }

        if (!complete) {
            success = false;
            return null;
        }

        return s.ToString();
    }

    protected static double ParseNumber(char[] json, ref int index, ref bool success)
    {
        EatWhitespace(json, ref index);

        int lastIndex = GetLastIndexOfNumber(json, index);
        int charLength = (lastIndex - index) + 1;

        double number;
        success = Double.TryParse(new string(json, index, charLength), NumberStyles.Any, CultureInfo.InvariantCulture, out number);

        index = lastIndex + 1;
        return number;
    }

    protected static int GetLastIndexOfNumber(char[] json, int index)
    {
        int lastIndex;

        for (lastIndex = index; lastIndex < json.Length; lastIndex++) {
            if ("0123456789+-.eE".IndexOf(json[lastIndex]) == -1) {
                break;
            }
        }
        return lastIndex - 1;
    }

    protected static void EatWhitespace(char[] json, ref int index)
    {
        for (; index < json.Length; index++) {
            if (" \t\n\r".IndexOf(json[index]) == -1) {
                break;
            }
        }
    }

    protected static int LookAhead(char[] json, int index)
    {
        int saveIndex = index;
        return NextToken(json, ref saveIndex);
    }

    protected static int NextToken(char[] json, ref int index)
    {
        EatWhitespace(json, ref index);

        if (index == json.Length) {
            return JSON.TOKEN_NONE;
        }

        char c = json[index];
        index++;
        switch (c) {
            case '{':
                return JSON.TOKEN_CURLY_OPEN;
            case '}':
                return JSON.TOKEN_CURLY_CLOSE;
            case '[':
                return JSON.TOKEN_SQUARED_OPEN;
            case ']':
                return JSON.TOKEN_SQUARED_CLOSE;
            case ',':
                return JSON.TOKEN_COMMA;
            case '"':
                return JSON.TOKEN_STRING;
            case '0': case '1': case '2': case '3': case '4':
            case '5': case '6': case '7': case '8': case '9':
            case '-':
                return JSON.TOKEN_NUMBER;
            case ':':
                return JSON.TOKEN_COLON;
        }
        index--;

        int remainingLength = json.Length - index;

        // false
        if (remainingLength >= 5) {
            if (json[index] == 'f' &&
                json[index + 1] == 'a' &&
                json[index + 2] == 'l' &&
                json[index + 3] == 's' &&
                json[index + 4] == 'e') {
                index += 5;
                return JSON.TOKEN_FALSE;
            }
        }

        // true
        if (remainingLength >= 4) {
            if (json[index] == 't' &&
                json[index + 1] == 'r' &&
                json[index + 2] == 'u' &&
                json[index + 3] == 'e') {
                index += 4;
                return JSON.TOKEN_TRUE;
            }
        }

        // null
        if (remainingLength >= 4) {
            if (json[index] == 'n' &&
                json[index + 1] == 'u' &&
                json[index + 2] == 'l' &&
                json[index + 3] == 'l') {
                index += 4;
                return JSON.TOKEN_NULL;
            }
        }

        return JSON.TOKEN_NONE;
    }

    protected static bool SerializeValue(object value, StringBuilder builder)
    {
        bool success = true;

        if (value is string) {
            success = SerializeString((string)value, builder);
        } else if (value is Hashtable) {
            success = SerializeObject((Hashtable)value, builder);
        } else if (value is ArrayList) {
            success = SerializeArray((ArrayList)value, builder);
        } else if ((value is Boolean) && ((Boolean)value == true)) {
            builder.Append("true");
        } else if ((value is Boolean) && ((Boolean)value == false)) {
            builder.Append("false");
        } else if (value is ValueType) {
            // thanks to ritchie for pointing out ValueType to me
            success = SerializeNumber(Convert.ToDouble(value), builder);
        } else if (value == null) {
            builder.Append("null");
        } else {
            success = false;
        }
        return success;
    }

    protected static bool SerializeObject(Hashtable anObject, StringBuilder builder)
    {
        builder.Append("{");

        IDictionaryEnumerator e = anObject.GetEnumerator();
        bool first = true;
        while (e.MoveNext()) {
            string key = e.Key.ToString();
            object value = e.Value;

            if (!first) {
                builder.Append(", ");
            }

            SerializeString(key, builder);
            builder.Append(":");
            if (!SerializeValue(value, builder)) {
                return false;
            }

            first = false;
        }

        builder.Append("}");
        return true;
    }

    protected static bool SerializeArray(ArrayList anArray, StringBuilder builder)
    {
        builder.Append("[");

        bool first = true;
        for (int i = 0; i < anArray.Count; i++) {
            object value = anArray[i];

            if (!first) {
                builder.Append(", ");
            }

            if (!SerializeValue(value, builder)) {
                return false;
            }

            first = false;
        }

        builder.Append("]");
        return true;
    }

    protected static bool SerializeString(string aString, StringBuilder builder)
    {
        builder.Append("\"");

        char[] charArray = aString.ToCharArray();
        for (int i = 0; i < charArray.Length; i++) {
            char c = charArray[i];
            if (c == '"') {
                builder.Append("\\\"");
            } else if (c == '\\') {
                builder.Append("\\\\");
            } else if (c == '\b') {
                builder.Append("\\b");
            } else if (c == '\f') {
                builder.Append("\\f");
            } else if (c == '\n') {
                builder.Append("\\n");
            } else if (c == '\r') {
                builder.Append("\\r");
            } else if (c == '\t') {
                builder.Append("\\t");
            } else {
                int codepoint = Convert.ToInt32(c);
                if ((codepoint >= 32) && (codepoint <= 126)) {
                    builder.Append(c);
                } else {
                    builder.Append("\\u" + Convert.ToString(codepoint, 16).PadLeft(4, '0'));
                }
            }
        }

        builder.Append("\"");
        return true;
    }

    protected static bool SerializeNumber(double number, StringBuilder builder)
    {
        builder.Append(Convert.ToString(number, CultureInfo.InvariantCulture));
        return true;
    }
}

//parse and show entire json in key-value pair
    Hashtable HTList = (Hashtable)JSON.JsonDecode("completejsonstring");
        public void GetData(Hashtable HT)
        {           
            IDictionaryEnumerator ienum = HT.GetEnumerator();
            while (ienum.MoveNext())
            {
                if (ienum.Value is ArrayList)
                {
                    ArrayList arnew = (ArrayList)ienum.Value;
                    foreach (object obj in arnew)                    
                    {
                        Hashtable hstemp = (Hashtable)obj;
                        GetData(hstemp);
                    }
                }
                else
                {
                    Console.WriteLine(ienum.Key + "=" + ienum.Value);
                }
            }
        }
0
A.P.S