Beispiel #1
0
        public void ObjectDepth()
        {
            string json      = "{ \"foo\": { \"x\": 1, \"y\": [ 0 ] } }";
            var    tokenizer = JsonTokenizer.FromTextReader(new StringReader(json));

            // If we had more tests like this, I'd introduce a helper method... but for one test, it's not worth it.
            Assert.AreEqual(0, tokenizer.ObjectDepth);
            Assert.AreEqual(JsonToken.StartObject, tokenizer.Next());
            Assert.AreEqual(1, tokenizer.ObjectDepth);
            Assert.AreEqual(JsonToken.Name("foo"), tokenizer.Next());
            Assert.AreEqual(1, tokenizer.ObjectDepth);
            Assert.AreEqual(JsonToken.StartObject, tokenizer.Next());
            Assert.AreEqual(2, tokenizer.ObjectDepth);
            Assert.AreEqual(JsonToken.Name("x"), tokenizer.Next());
            Assert.AreEqual(2, tokenizer.ObjectDepth);
            Assert.AreEqual(JsonToken.Value(1), tokenizer.Next());
            Assert.AreEqual(2, tokenizer.ObjectDepth);
            Assert.AreEqual(JsonToken.Name("y"), tokenizer.Next());
            Assert.AreEqual(2, tokenizer.ObjectDepth);
            Assert.AreEqual(JsonToken.StartArray, tokenizer.Next());
            Assert.AreEqual(2, tokenizer.ObjectDepth); // Depth hasn't changed in array
            Assert.AreEqual(JsonToken.Value(0), tokenizer.Next());
            Assert.AreEqual(2, tokenizer.ObjectDepth);
            Assert.AreEqual(JsonToken.EndArray, tokenizer.Next());
            Assert.AreEqual(2, tokenizer.ObjectDepth);
            Assert.AreEqual(JsonToken.EndObject, tokenizer.Next());
            Assert.AreEqual(1, tokenizer.ObjectDepth);
            Assert.AreEqual(JsonToken.EndObject, tokenizer.Next());
            Assert.AreEqual(0, tokenizer.ObjectDepth);
            Assert.AreEqual(JsonToken.EndDocument, tokenizer.Next());
            Assert.AreEqual(0, tokenizer.ObjectDepth);
        }
Beispiel #2
0
 public void ObjectMixedType()
 {
     AssertTokens(@"{'a': 1, 'b': 'bar', 'c': null, 'd': false, 'e': true, 
                    'f': [2], 'g': {'x':'y' }}",
                  JsonToken.StartObject,
                  JsonToken.Name("a"),
                  JsonToken.Value(1),
                  JsonToken.Name("b"),
                  JsonToken.Value("bar"),
                  JsonToken.Name("c"),
                  JsonToken.Null,
                  JsonToken.Name("d"),
                  JsonToken.False,
                  JsonToken.Name("e"),
                  JsonToken.True,
                  JsonToken.Name("f"),
                  JsonToken.StartArray,
                  JsonToken.Value(2),
                  JsonToken.EndArray,
                  JsonToken.Name("g"),
                  JsonToken.StartObject,
                  JsonToken.Name("x"),
                  JsonToken.Value("y"),
                  JsonToken.EndObject,
                  JsonToken.EndObject);
 }
Beispiel #3
0
 public void ArrayMixedType()
 {
     AssertTokens("[1, 'foo', null, false, true, [2], {'x':'y' }]",
                  JsonToken.StartArray,
                  JsonToken.Value(1),
                  JsonToken.Value("foo"),
                  JsonToken.Null,
                  JsonToken.False,
                  JsonToken.True,
                  JsonToken.StartArray,
                  JsonToken.Value(2),
                  JsonToken.EndArray,
                  JsonToken.StartObject,
                  JsonToken.Name("x"),
                  JsonToken.Value("y"),
                  JsonToken.EndObject,
                  JsonToken.EndArray);
 }
Beispiel #4
0
        /// <summary>
        /// Returns the next JSON token in the stream. An EndDocument token is returned to indicate the end of the stream,
        /// after which point <c>Next()</c> should not be called again.
        /// </summary>
        /// <remarks>
        /// This method essentially just loops through characters skipping whitespace, validating and
        /// changing state (e.g. from ObjectBeforeColon to ObjectAfterColon)
        /// until it reaches something which will be a genuine token (e.g. a start object, or a value) at which point
        /// it returns the token. Although the method is large, it would be relatively hard to break down further... most
        /// of it is the large switch statement, which sometimes returns and sometimes doesn't.
        /// </remarks>
        /// <returns>The next token in the stream. This is never null.</returns>
        /// <exception cref="InvalidOperationException">This method is called after an EndDocument token has been returned</exception>
        internal JsonToken Next()
        {
            if (bufferedToken != null)
            {
                var ret = bufferedToken;
                bufferedToken = null;
                return(ret);
            }
            if (state == State.ReaderExhausted)
            {
                throw new InvalidOperationException("Next() called after end of document");
            }
            while (true)
            {
                var next = reader.Read();
                if (next == null)
                {
                    ValidateState(State.ExpectedEndOfDocument, "Unexpected end of document in state: ");
                    state = State.ReaderExhausted;
                    return(JsonToken.EndDocument);
                }
                switch (next.Value)
                {
                // Skip whitespace between tokens
                case ' ':
                case '\t':
                case '\r':
                case '\n':
                    break;

                case ':':
                    ValidateState(State.ObjectBeforeColon, "Invalid state to read a colon: ");
                    state = State.ObjectAfterColon;
                    break;

                case ',':
                    ValidateState(State.ObjectAfterProperty | State.ArrayAfterValue, "Invalid state to read a colon: ");
                    state = state == State.ObjectAfterProperty ? State.ObjectAfterComma : State.ArrayAfterComma;
                    break;

                case '"':
                    string stringValue = ReadString();
                    if ((state & (State.ObjectStart | State.ObjectAfterComma)) != 0)
                    {
                        state = State.ObjectBeforeColon;
                        return(JsonToken.Name(stringValue));
                    }
                    else
                    {
                        ValidateAndModifyStateForValue("Invalid state to read a double quote: ");
                        return(JsonToken.Value(stringValue));
                    }

                case '{':
                    ValidateState(ValueStates, "Invalid state to read an open brace: ");
                    state = State.ObjectStart;
                    containerStack.Push(ContainerType.Object);
                    return(JsonToken.StartObject);

                case '}':
                    ValidateState(State.ObjectAfterProperty | State.ObjectStart, "Invalid state to read a close brace: ");
                    PopContainer();
                    return(JsonToken.EndObject);

                case '[':
                    ValidateState(ValueStates, "Invalid state to read an open square bracket: ");
                    state = State.ArrayStart;
                    containerStack.Push(ContainerType.Array);
                    return(JsonToken.StartArray);

                case ']':
                    ValidateState(State.ArrayAfterValue | State.ArrayStart, "Invalid state to read a close square bracket: ");
                    PopContainer();
                    return(JsonToken.EndArray);

                case 'n':     // Start of null
                    ConsumeLiteral("null");
                    ValidateAndModifyStateForValue("Invalid state to read a null literal: ");
                    return(JsonToken.Null);

                case 't':     // Start of true
                    ConsumeLiteral("true");
                    ValidateAndModifyStateForValue("Invalid state to read a true literal: ");
                    return(JsonToken.True);

                case 'f':     // Start of false
                    ConsumeLiteral("false");
                    ValidateAndModifyStateForValue("Invalid state to read a false literal: ");
                    return(JsonToken.False);

                case '-':     // Start of a number
                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9':
                    double number = ReadNumber(next.Value);
                    ValidateAndModifyStateForValue("Invalid state to read a number token: ");
                    return(JsonToken.Value(number));

                default:
                    throw new InvalidProtocolBufferException("Invalid first character of token: " + next.Value);
                }
            }
        }
Beispiel #5
0
 public void SimpleObject()
 {
     AssertTokens("{'x': 'y'}",
                  JsonToken.StartObject, JsonToken.Name("x"), JsonToken.Value("y"), JsonToken.EndObject);
 }