
com.dyuproject.protostuff.JsonXIOUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of protostuff-json Show documentation
Show all versions of protostuff-json Show documentation
protostuff serialization using json format
The newest version!
//========================================================================
//Copyright 2007-2010 David Yu [email protected]
//------------------------------------------------------------------------
//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 java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
/**
* Json serialization via {@link JsonXOutput}.
*
*
* @author David Yu
* @created Jul 2, 2010
*/
public final class JsonXIOUtil
{
private static final byte[] EMPTY_ARRAY = new byte[]{
(byte)'[', (byte)']'
};
static final int TMP_CBUF_LEN = Integer.getInteger("jsonx.tmp_cbuf_len", 256),
ERR_PREVIEW_MAX_LEN = Integer.getInteger("jsonx.err_preview_max_len", 90);
public static byte[] toByteArray(T message, Schema schema, boolean numeric,
LinkedBuffer buffer)
{
return toByteArray(message, schema, numeric ? JsonFlags.NUMERIC : 0, buffer);
}
public static byte[] toByteArray(T message, Schema schema, int flags,
LinkedBuffer buffer)
{
if(buffer.start != buffer.offset)
throw new IllegalArgumentException("Buffer previously used and had not been reset.");
final JsonXOutput output = new JsonXOutput(buffer, flags, schema);
try
{
output.writeStartObject();
schema.writeTo(output, message);
if(output.isLastRepeated())
output.writeEndArray();
output.writeEndObject();
}
catch (IOException e)
{
throw new RuntimeException("Serializing to a byte array threw an IOException " +
"(should never happen).", e);
}
return output.toByteArray();
}
/**
* Serializes the {@code message} into a {@link LinkedBuffer} via {@link JsonXOutput}
* using the given {@code schema} with the supplied buffer.
*/
public static void writeTo(LinkedBuffer buffer, T message, Schema schema,
boolean numeric)
{
writeTo(buffer, message, schema, numeric ? JsonFlags.NUMERIC : 0);
}
/**
* Serializes the {@code message} into a {@link LinkedBuffer} via {@link JsonXOutput}
* using the given {@code schema} with the supplied buffer.
*/
public static void writeTo(LinkedBuffer buffer, T message, Schema schema,
int flags)
{
if(buffer.start != buffer.offset)
throw new IllegalArgumentException("Buffer previously used and had not been reset.");
final JsonXOutput output = new JsonXOutput(buffer, flags, schema);
try
{
output.writeStartObject();
schema.writeTo(output, message);
if(output.isLastRepeated())
output.writeEndArray();
output.writeEndObject();
}
catch (IOException e)
{
throw new RuntimeException("Serializing to a byte array threw an IOException " +
"(should never happen).", e);
}
}
/**
* Serializes the {@code message} into an {@link OutputStream} via {@link JsonXOutput} with the
* supplied buffer.
*/
public static > void writeTo(OutputStream out, T message, boolean numeric,
LinkedBuffer buffer)
throws IOException
{
writeTo(out, message, message.cachedSchema(), numeric, buffer);
}
/**
* Serializes the {@code message} into an {@link OutputStream} via {@link JsonXOutput}
* using the given {@code schema}.
*/
public static void writeTo(OutputStream out, T message, Schema schema, boolean numeric,
LinkedBuffer buffer) throws IOException
{
writeTo(out, message, schema, numeric ? JsonFlags.NUMERIC : 0, buffer);
}
/**
* Serializes the {@code message} into an {@link OutputStream} via {@link JsonXOutput}
* using the given {@code schema}.
*/
public static void writeTo(OutputStream out, T message, Schema schema, int flags,
LinkedBuffer buffer) throws IOException
{
if(buffer.start != buffer.offset)
throw new IllegalArgumentException("Buffer previously used and had not been reset.");
final JsonXOutput output = new JsonXOutput(buffer, out, flags, schema);
output.writeStartObject();
schema.writeTo(output, message);
if(output.isLastRepeated())
output.writeEndArray();
output.writeEndObject();
LinkedBuffer.writeTo(out, buffer);
}
/**
* Serializes the {@code messages} into the {@link LinkedBuffer} using the given schema.
*/
public static void writeListTo(LinkedBuffer buffer,
List messages, Schema schema, boolean numeric)
{
writeListTo(buffer, messages, schema, numeric ? JsonFlags.NUMERIC : 0);
}
/**
* Serializes the {@code messages} into the {@link LinkedBuffer} using the given schema.
*/
public static void writeListTo(LinkedBuffer buffer,
List messages, Schema schema, int flags)
{
if(buffer.start != buffer.offset)
throw new IllegalArgumentException("Buffer previously used and had not been reset.");
final JsonXOutput output = new JsonXOutput(buffer, flags, schema);
try
{
if (messages.isEmpty())
{
output.tail = output.sink.writeByteArray(EMPTY_ARRAY, output, output.tail);
return;
}
output.writeStartArray();
boolean first = true;
for(T m : messages)
{
if(first)
{
first = false;
output.writeStartObject();
}
else
output.writeCommaAndStartObject();
schema.writeTo(output, m);
if(output.isLastRepeated())
output.writeEndArray();
output.writeEndObject().reset();
}
output.writeEndArray();
}
catch(IOException e)
{
throw new RuntimeException("Serializing to a byte array threw an IOException " +
"(should never happen).", e);
}
}
/**
* Serializes the {@code messages} into the stream using the given schema with the
* supplied buffer.
*/
public static void writeListTo(OutputStream out, List messages, Schema schema,
boolean numeric, LinkedBuffer buffer) throws IOException
{
writeListTo(out, messages, schema, numeric ? JsonFlags.NUMERIC : 0, buffer);
}
/**
* Serializes the {@code messages} into the stream using the given schema with the
* supplied buffer.
*/
public static void writeListTo(OutputStream out, List messages, Schema schema,
int flags, LinkedBuffer buffer) throws IOException
{
if(buffer.start != buffer.offset)
throw new IllegalArgumentException("Buffer previously used and had not been reset.");
if (messages.isEmpty())
{
out.write(EMPTY_ARRAY);
return;
}
final JsonXOutput output = new JsonXOutput(buffer, out, flags, schema);
output.writeStartArray();
boolean first = true;
for(T m : messages)
{
if(first)
{
first = false;
output.writeStartObject();
}
else
output.writeCommaAndStartObject();
schema.writeTo(output, m);
if(output.isLastRepeated())
output.writeEndArray();
output.writeEndObject().reset();
}
output.writeEndArray();
LinkedBuffer.writeTo(out, buffer);
}
/**
* Parses the {@code messages} from the parser using the given {@code schema}.
*/
public static List parseListFrom(byte[] data, Schema schema) throws IOException
{
return parseListFrom(data, 0, data.length, schema, TMP_CBUF_LEN, true);
}
/**
* Parses the {@code messages} from the parser using the given {@code schema}.
*/
public static List parseListFrom(byte[] data, int offset, int len, Schema schema) throws IOException
{
return parseListFrom(data, offset, len, schema, TMP_CBUF_LEN, true);
}
/**
* Parses the {@code messages} from the parser using the given {@code schema}.
*/
public static List parseListFrom(byte[] data, int offset, int len,
Schema schema,
int charBufSize, boolean charBufAsLimit) throws IOException
{
return parseListFrom(data, offset, len, schema, false,
new char[charBufSize], 0, charBufSize, charBufAsLimit);
}
private static int nextOffset(byte[] data, int i, int limit)
{
while (i < limit && Character.isWhitespace((char)data[i])) i++;
return i;
}
/**
* Parses the {@code messages} from the parser using the given {@code schema}.
*/
public static List parseListFrom(final byte[] data, final int offset, final int len,
Schema schema, final boolean allowQuotedInt64,
char[] cbuf, int coffset, int clen, boolean charBufAsLimit) throws IOException
{
return parseListFrom(data, offset, len, schema, allowQuotedInt64, (byte)0,
cbuf, coffset, clen, charBufAsLimit);
}
/**
* Parses the {@code messages} from the parser using the given {@code schema}.
*/
public static List parseListFrom(final byte[] data, final int offset, final int len,
Schema schema, final boolean allowQuotedInt64, byte alphaNumericPrefixChar,
char[] cbuf, int coffset, int clen, boolean charBufAsLimit) throws IOException
{
final int limit = offset + len;
int i = nextOffset(data, offset, limit);
if (i == limit)
{
throw new JsonInputException("Expected token: [ but was truncated on message: " +
schema.messageFullName());
}
byte b;
if (JsonXByteArrayInput.START_ARRAY != (b = data[i]))
{
cbuf[coffset] = (char)b;
throw new JsonInputException("Expected token: [ but was " +
new String(cbuf, coffset, 1) + " on message: " +
schema.messageFullName());
}
if (limit == (i = nextOffset(data, i + 1, limit)))
{
throw new JsonInputException("Input was truncated on message: " +
schema.messageFullName());
}
final ArrayList list = new ArrayList();
if (JsonXByteArrayInput.END_ARRAY == (b = data[i]))
return list;
final JsonXByteArrayInput input = new JsonXByteArrayInput(
data, i, limit - i, allowQuotedInt64, alphaNumericPrefixChar,
cbuf, coffset, clen, charBufAsLimit, ERR_PREVIEW_MAX_LEN);
for (;; b = data[i])
{
if (JsonXByteArrayInput.START_OBJECT != (b = input.nextToken()))
{
cbuf[coffset] = (char)b;
throw new JsonInputException("Expected token: { but was " +
new String(cbuf, coffset, 1) + " on message " +
schema.messageFullName());
}
input.nextToken();
final T message = schema.newMessage();
schema.mergeFrom(input, message);
if (JsonXByteArrayInput.END_OBJECT != (b = input.currentToken()))
{
cbuf[coffset] = (char)b;
throw new JsonInputException("Expected token: } but was " +
new String(cbuf, coffset, 1) + " on message " +
schema.messageFullName());
}
list.add(message);
if (limit <= (i = nextOffset(data, input.currentOffset(), limit)))
{
throw new JsonInputException("Input was truncated on message: " +
schema.messageFullName());
}
if (JsonXByteArrayInput.END_ARRAY == (b = data[i]))
break;
if (JsonXByteArrayInput.COMMA != b)
{
cbuf[coffset] = (char)b;
throw new JsonInputException("Expected token: , but was " +
new String(cbuf, coffset, 1) + " on message " +
schema.messageFullName());
}
if (limit == (i = nextOffset(data, i + 1, limit)))
{
throw new JsonInputException("Input was truncated on message: " +
schema.messageFullName());
}
input.reset(i);
}
return list;
}
public static void mergeFrom(byte[] data, T message, Schema schema) throws IOException
{
mergeFrom(data, 0, data.length, message, schema, TMP_CBUF_LEN, true);
}
public static void mergeFrom(byte[] data, int offset, int len, T message, Schema schema) throws IOException
{
mergeFrom(data, offset, len, message, schema, TMP_CBUF_LEN, true);
}
public static void mergeFrom(byte[] data, int offset, int len,
T message, Schema schema,
int charBufSize, boolean charBufAsLimit) throws IOException
{
mergeFrom(data, offset, len, message, schema, false,
new char[charBufSize], 0, charBufSize, charBufAsLimit);
}
public static void mergeFrom(byte[] data, int offset, int len,
T message, Schema schema, final boolean allowQuotedInt64,
char[] cbuf, int coffset, int clen, boolean charBufAsLimit) throws IOException
{
mergeFrom(data, offset, len, message, schema, allowQuotedInt64, (byte)0,
cbuf, coffset, clen, charBufAsLimit);
}
public static void mergeFrom(byte[] data, int offset, int len,
T message, Schema schema, final boolean allowQuotedInt64,
byte alphaNumericPrefixChar,
char[] cbuf, int coffset, int clen, boolean charBufAsLimit) throws IOException
{
if (len < 2)
{
throw new JsonInputException("Input must have a minimum length of 2: '{}' on message " +
schema.messageFullName());
}
//if ('{' == data[offset] && '}' == data[offset+1]) return;
final JsonXByteArrayInput input = new JsonXByteArrayInput(
data, offset, len, allowQuotedInt64, alphaNumericPrefixChar,
cbuf, coffset, clen, charBufAsLimit, ERR_PREVIEW_MAX_LEN);
mergeFrom(input, message, schema);
}
static void mergeFrom(JsonXByteArrayInput input,
T message, Schema schema) throws IOException
{
if (JsonXByteArrayInput.START_OBJECT != input.nextToken())
{
throw new JsonInputException("Expected token: { but was " +
(char)input.currentToken() + " on message " +
schema.messageFullName());
}
//if (JsonXByteArrayInput.END_OBJECT == input.nextToken())
// return;
input.nextToken();
schema.mergeFrom(input, message);
if (JsonXByteArrayInput.END_OBJECT != input.currentToken())
{
throw new JsonInputException("Expected token: } but was " +
(char)input.currentToken() + " on message " +
schema.messageFullName());
}
}
/**
* Creates a json pipe from a byte array.
*/
public static Pipe newPipe(byte[] data) throws IOException
{
return newPipe(data, 0, data.length, TMP_CBUF_LEN, true);
}
/**
* Creates a json pipe from a byte array.
*/
public static Pipe newPipe(byte[] data, int offset, int len)
throws IOException
{
return newPipe(data, offset, len, TMP_CBUF_LEN, true);
}
/**
* Creates a json pipe from a byte array.
*/
public static Pipe newPipe(byte[] data, int offset, int len,
int charBufSize, boolean charBufAsLimit) throws IOException
{
return newPipe(data, offset, len, false,
new char[charBufSize], 0, charBufSize, charBufAsLimit);
}
/**
* Creates a json pipe from a byte array.
*/
public static Pipe newPipe(byte[] data, int offset, int len,
final boolean allowQuotedInt64,
char[] cbuf, int coffset, int clen, boolean charBufAsLimit) throws IOException
{
return newPipe(data, offset, len, allowQuotedInt64, (byte)0,
cbuf, coffset, clen, charBufAsLimit);
}
/**
* Creates a json pipe from a byte array.
*/
public static Pipe newPipe(byte[] data, int offset, int len,
final boolean allowQuotedInt64, byte alphaNumericPrefixChar,
char[] cbuf, int coffset, int clen, boolean charBufAsLimit) throws IOException
{
if (len < 2)
throw new JsonInputException("Input must have a minimum length of 2: '{}'");
//if ('{' == data[offset] && '}' == data[offset+1]) return;
final JsonXByteArrayInput jsonInput = new JsonXByteArrayInput(
data, offset, len, allowQuotedInt64, alphaNumericPrefixChar,
cbuf, coffset, clen, charBufAsLimit, ERR_PREVIEW_MAX_LEN);
return new Pipe()
{
protected Input begin(Pipe.Schema> pipeSchema) throws IOException
{
if (JsonXByteArrayInput.START_OBJECT != jsonInput.nextToken())
{
throw new JsonInputException("Expected token: { but was " +
(char)jsonInput.currentToken() + " on message " +
pipeSchema.wrappedSchema.messageFullName());
}
//if (JsonXByteArrayInput.END_OBJECT == jsonInput.nextToken())
// return;
jsonInput.nextToken();
return jsonInput;
}
protected void end(Pipe.Schema> pipeSchema, Input input,
boolean cleanupOnly) throws IOException
{
if (cleanupOnly)
return;
assert input == jsonInput;
if (JsonXByteArrayInput.END_OBJECT != jsonInput.currentToken())
{
throw new JsonInputException("Expected token: } but was " +
(char)jsonInput.currentToken() + " on message " +
pipeSchema.wrappedSchema.messageFullName());
}
}
};
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy