Package com.dyuproject.protostuff

Source Code of com.dyuproject.protostuff.JsonInput

//========================================================================
//Copyright 2007-2009 David Yu dyuproject@gmail.com
//------------------------------------------------------------------------
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//http://www.apache.org/licenses/LICENSE-2.0
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.
//========================================================================

package com.dyuproject.protostuff;

import static org.codehaus.jackson.JsonToken.END_ARRAY;
import static org.codehaus.jackson.JsonToken.END_OBJECT;
import static org.codehaus.jackson.JsonToken.FIELD_NAME;
import static org.codehaus.jackson.JsonToken.START_ARRAY;
import static org.codehaus.jackson.JsonToken.START_OBJECT;
import static org.codehaus.jackson.JsonToken.VALUE_FALSE;
import static org.codehaus.jackson.JsonToken.VALUE_NULL;
import static org.codehaus.jackson.JsonToken.VALUE_STRING;
import static org.codehaus.jackson.JsonToken.VALUE_TRUE;

import java.io.IOException;

import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonToken;

/**
* An input used for reading data with json format.
*
* @author David Yu
* @created Nov 20, 2009
*/
public final class JsonInput implements Input
{
   
    /**
     * The wrapped json parser.
     */
    public final JsonParser parser;
   
    /**
     * If true, the field number will be used on json keys.
     */
    public final boolean numeric;
   
    private boolean lastRepeated;
    private String lastName;
    private int lastNumber;
   
    public JsonInput(JsonParser parser)
    {
        this(parser, false);
    }
   
    public JsonInput(JsonParser parser, boolean numeric)
    {
        this.parser = parser;
        this.numeric = numeric;
    }
   
    /**
     * Returns whether the incoming messages' field names are numeric.
     */
    public boolean isNumeric()
    {
        return numeric;
    }
   
    /**
     * Gets the last field number read.
     */
    public int getLastNumber()
    {
        return lastNumber;
    }
   
    /**
     * Returns true if the last read field was a repeated field.
     */
    public boolean isLastRepeated()
    {
        return lastRepeated;
    }
   
    /**
     * Resets this input.
     */
    public JsonInput reset()
    {
        lastRepeated = false;
        lastName = null;
        lastNumber = 0;
        return this;
    }

    public <T> void handleUnknownField(int fieldNumber, Schema<T> schema) throws IOException
    {
        if(parser.getCurrentToken().isScalarValue())
        {
            // numeric json
            // we can skip this unknown field
            if(lastRepeated)
            {
                lastRepeated = false;
                // skip the scalar elements
                while(parser.nextToken() != END_ARRAY);
            }
            return;
        }
       
        throw new JsonInputException("Unknown field: " +
                (numeric ? fieldNumber : lastName) +
                " on message " +
                schema.messageFullName());
    }
   
    public <T> int readFieldNumber(final Schema<T> schema) throws IOException
    {
        if(lastRepeated)
        {
            if(parser.getCurrentToken() == VALUE_NULL)
            {
                // skip null elements
                JsonToken jt;
                while(VALUE_NULL == (jt = parser.nextToken()));
               
                if(jt == END_ARRAY)
                {
                    // remaining elements were all null
                   
                    // move to the next field
                    lastRepeated = false;
                    return readFieldNumber(schema, parser);
                }
            }
           
            return lastNumber;
        }
       
        return readFieldNumber(schema, parser);
    }

    private <T> int readFieldNumber(final Schema<T> schema, final JsonParser parser)
    throws IOException
    {
        for(;;)
        {
            if(parser.nextToken() == END_OBJECT)
                return 0;
           
            if(parser.getCurrentToken() != FIELD_NAME)
            {
                throw new JsonInputException("Expected token: $field: but was " +
                        parser.getCurrentToken() + " on message " + schema.messageFullName());
            }
           
            final String name = parser.getCurrentName();
           
            // move to the next token
            if(parser.nextToken() == START_ARRAY)
            {
                JsonToken jt = parser.nextToken();
               
                // if empty array, read the next field
                if(jt == END_ARRAY)
                    continue;
               
                if(jt == VALUE_NULL)
                {
                    // skip null elements
                    while(VALUE_NULL == (jt = parser.nextToken()));
                   
                    // all elements were null.
                    if(jt == END_ARRAY)
                        continue;
                }

                final int number = numeric ? Integer.parseInt(name) :
                    schema.getFieldNumber(name);
               
                if(number == 0)
                {
                    // unknown field
                    if(parser.getCurrentToken().isScalarValue())
                    {
                        // skip the scalar elements
                        while(parser.nextToken() != END_ARRAY);
                       
                        continue;
                    }
                   
                    throw new JsonInputException("Unknown field: " + name + " on message " +
                            schema.messageFullName());
                }
               
                lastRepeated = true;
                lastName = name;
                lastNumber = number;
               
                return number;
            }
           
            // skip null value
            if(parser.getCurrentToken() == VALUE_NULL)
                continue;
           
            final int number = numeric ? Integer.parseInt(name) :
                schema.getFieldNumber(name);
           
            if(number == 0)
            {
                // we can skip this unknown field
                if(parser.getCurrentToken().isScalarValue())
                    continue;
               
                throw new JsonInputException("Unknown field: " + name + " on message " +
                        schema.messageFullName());
            }
           
            lastName = name;
            lastNumber = number;
           
            return number;
        }
    }

    public boolean readBool() throws IOException
    {
        final JsonToken jt = parser.getCurrentToken();
        if(lastRepeated && parser.nextToken()==END_ARRAY)
            lastRepeated = false;
       
        if(jt==VALUE_TRUE)
            return true;
        if(jt==VALUE_FALSE)
            return false;
       
        throw new JsonInputException("Expected token: true/false but was " + jt);
    }

    public byte[] readByteArray() throws IOException
    {
        final byte[] value = parser.getBinaryValue();
       
        if(lastRepeated && parser.nextToken()==END_ARRAY)
            lastRepeated = false;
       
        return value;
    }

    public ByteString readBytes() throws IOException
    {
        return ByteString.wrap(readByteArray());
    }

    public double readDouble() throws IOException
    {
        final double value = parser.getDoubleValue();
       
        if(lastRepeated && parser.nextToken()==END_ARRAY)
            lastRepeated = false;
       
        return value;
    }

    public int readEnum() throws IOException
    {
        return readInt32();
    }

    public int readFixed32() throws IOException
    {
        return readInt32();
    }

    public long readFixed64() throws IOException
    {
        return readInt64();
    }

    public float readFloat() throws IOException
    {
        final float value = parser.getFloatValue();
       
        if(lastRepeated && parser.nextToken()==END_ARRAY)
            lastRepeated = false;
       
        return value;
    }

    public int readInt32() throws IOException
    {
        final int value = parser.getIntValue();
       
        if(lastRepeated && parser.nextToken()==END_ARRAY)
            lastRepeated = false;
       
        return value;
    }

    public long readInt64() throws IOException
    {
        final long value = parser.getLongValue();
       
        if(lastRepeated && parser.nextToken()==END_ARRAY)
            lastRepeated = false;
       
        return value;
    }

    public int readSFixed32() throws IOException
    {
        return readInt32();
    }

    public long readSFixed64() throws IOException
    {
        return readInt64();
    }

    public int readSInt32() throws IOException
    {
        return readInt32();
    }

    public long readSInt64() throws IOException
    {
        return readInt64();
    }

    public String readString() throws IOException
    {
        if(parser.getCurrentToken() != VALUE_STRING)
            throw new JsonInputException("Expected token: string but was " + parser.getCurrentToken());
       
        final String value = parser.getText();
       
        if(lastRepeated && parser.nextToken()==END_ARRAY)
            lastRepeated = false;
       
        return value;
    }

    public int readUInt32() throws IOException
    {
        return readInt32();
    }

    public long readUInt64() throws IOException
    {
        return readInt64();
    }

    public <T> T mergeObject(T value, final Schema<T> schema) throws IOException
    {
        if(parser.getCurrentToken() != START_OBJECT)
        {
            throw new JsonInputException("Expected token: { but was " +
                    parser.getCurrentToken() + " on " + lastName + " of message " +
                    schema.messageFullName());
        }
       
        final int lastNumber = this.lastNumber;
        final boolean lastRepeated = this.lastRepeated;
        final String lastName = this.lastName;
       
        // reset
        this.lastRepeated = false;
       
        if(value == null)
            value = schema.newMessage();
       
        schema.mergeFrom(this, value);
       
        if(parser.getCurrentToken() != END_OBJECT)
        {
            throw new JsonInputException("Expected token: } but was " +
                    parser.getCurrentToken() + " on " + lastName + " of message " +
                    schema.messageFullName());
        }
       
        if(!schema.isInitialized(value))
            throw new UninitializedMessageException(value, schema);
       
        // restore state
        this.lastNumber = lastNumber;
        this.lastRepeated = lastRepeated;
        this.lastName = lastName;
       
        if(lastRepeated && parser.nextToken()==END_ARRAY)
            this.lastRepeated = false;
       
        return value;
    }
   
    public void transferByteRangeTo(Output output, boolean utf8String, int fieldNumber,
            boolean repeated) throws IOException
    {
        if(utf8String)
            output.writeString(fieldNumber, readString(), repeated);
        else
            output.writeByteArray(fieldNumber, readByteArray(), repeated);
    }

}
TOP

Related Classes of com.dyuproject.protostuff.JsonInput

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.