add new method JSON#parse(InputStream, Context)

This commit is contained in:
shaojin.wensj 2024-01-31 01:10:39 +08:00
parent 9493d46ba9
commit 69538bbca6
5 changed files with 288 additions and 14 deletions

View File

@ -246,6 +246,32 @@ public interface JSON {
}
}
/**
* Parses the json stream as a {@link JSONArray} or {@link JSONObject}.
* Returns {@code null} if received {@link String} is {@code null} or empty.
*
* @param in the specified stream to be parsed
* @param context the specified custom context
* @return either {@link JSONArray} or {@link JSONObject} or null
* @throws JSONException If a parsing error occurs
* @throws NullPointerException If received context is null
* @since 2.0.47
*/
static Object parse(InputStream in, JSONReader.Context context) {
if (in == null) {
return null;
}
ObjectReader<?> objectReader = context.getObjectReader(Object.class);
try (JSONReaderUTF8 reader = new JSONReaderUTF8(context, in)) {
Object object = objectReader.readObject(reader, null, null, 0);
if (reader.ch != EOI && (context.features & IgnoreCheckClose.mask) == 0) {
throw new JSONException(reader.info("input not end"));
}
return object;
}
}
/**
* Parses the json string as a {@link JSONObject}. Returns {@code null}
* if received {@link String} is {@code null} or empty or its content is null.
@ -570,6 +596,40 @@ public interface JSON {
}
}
/**
* Parses the json stream as a {@link JSONObject}. Returns {@code null} if
* received {@link InputStream} is {@code null} or closed or its content is null.
*
* @param input the specified stream to be parsed
* @param charset the specified charset of the stream
* @param context the specified custom context
* @return {@link JSONObject} or {@code null}
* @throws JSONException If a parsing error occurs
*
* @since 2.0.47
*/
static JSONObject parseObject(InputStream input, Charset charset, JSONReader.Context context) {
if (input == null) {
return null;
}
try (JSONReader reader = JSONReader.of(input, charset, context)) {
if (reader.isEnd()) {
return null;
}
JSONObject object = new JSONObject();
reader.read(object, 0);
if (reader.resolveTasks != null) {
reader.handleResolveTasks(object);
}
if (reader.ch != EOI && (context.features & IgnoreCheckClose.mask) == 0) {
throw new JSONException(reader.info("input not end"));
}
return object;
}
}
/**
* Parses the json stream of the url as a {@link JSONObject}.
* Returns {@code null} if received {@link URL} is {@code null}.
@ -1861,6 +1921,76 @@ public interface JSON {
}
}
/**
* Parses the json stream as a {@link T}. Returns {@code null}
* if received {@link InputStream} is {@code null} or its content is null.
*
* @param input the specified stream to be parsed
* @param type the specified actual type of {@link T}
* @param context the specified custom context
* @return {@link T} or {@code null}
* @throws JSONException If a parsing error occurs
*/
@SuppressWarnings("unchecked")
static <T> T parseObject(InputStream input, Charset charset, Type type, JSONReader.Context context) {
if (input == null) {
return null;
}
boolean fieldBased = (context.features & JSONReader.Feature.FieldBased.mask) != 0;
ObjectReader<T> objectReader = context.provider.getObjectReader(type, fieldBased);
try (JSONReader reader = JSONReader.of(input, charset, context)) {
if (reader.isEnd()) {
return null;
}
T object = objectReader.readObject(reader, type, null, 0);
if (reader.resolveTasks != null) {
reader.handleResolveTasks(object);
}
if (reader.ch != EOI && (context.features & IgnoreCheckClose.mask) == 0) {
throw new JSONException(reader.info("input not end"));
}
return object;
}
}
/**
* Parses the json stream as a {@link T}. Returns {@code null}
* if received {@link InputStream} is {@code null} or its content is null.
*
* @param input the specified stream to be parsed
* @param type the specified actual type of {@link T}
* @param context the specified custom context
* @return {@link T} or {@code null}
* @throws JSONException If a parsing error occurs
*/
@SuppressWarnings("unchecked")
static <T> T parseObject(InputStream input, Charset charset, Class<T> type, JSONReader.Context context) {
if (input == null) {
return null;
}
boolean fieldBased = (context.features & JSONReader.Feature.FieldBased.mask) != 0;
ObjectReader<T> objectReader = context.provider.getObjectReader(type, fieldBased);
try (JSONReader reader = JSONReader.of(input, charset, context)) {
if (reader.isEnd()) {
return null;
}
T object = objectReader.readObject(reader, type, null, 0);
if (reader.resolveTasks != null) {
reader.handleResolveTasks(object);
}
if (reader.ch != EOI && (context.features & IgnoreCheckClose.mask) == 0) {
throw new JSONException(reader.info("input not end"));
}
return object;
}
}
/**
* Parses the json stream of the url as {@link T}.
* Returns {@code null} if received {@link URL} is {@code null}.
@ -2498,6 +2628,37 @@ public interface JSON {
}
}
/**
* Parses the json stream as a {@link JSONArray}. Returns {@code null}
* if received {@link InputStream} is {@code null} or its content is null.
*
* @param in the specified stream to be parsed
* @param charset the specified charset of the stream
* @param context the specified custom context
* @return {@link JSONArray} or {@code null}
* @throws JSONException If an I/O error or parsing error occurs
*/
static JSONArray parseArray(InputStream in, Charset charset, JSONReader.Context context) {
if (in == null) {
return null;
}
try (JSONReader reader = JSONReader.of(in, charset, context)) {
if (reader.nextIfNull()) {
return null;
}
JSONArray array = new JSONArray();
reader.read(array);
if (reader.resolveTasks != null) {
reader.handleResolveTasks(array);
}
if (reader.ch != EOI && (context.features & IgnoreCheckClose.mask) == 0) {
throw new JSONException(reader.info("input not end"));
}
return array;
}
}
/**
* Parses the json string as a list of {@link T}. Returns
* {@code null} if received {@link String} is {@code null} or empty.

View File

@ -302,7 +302,6 @@ public interface JSONB {
static Object parse(byte[] jsonbBytes, JSONReader.Feature... features) {
ObjectReaderProvider provider = defaultObjectReaderProvider;
JSONReader.Context context = new JSONReader.Context(provider, features);
boolean fieldBased = (context.features & JSONReader.Feature.FieldBased.mask) != 0;
try (JSONReaderJSONB reader = new JSONReaderJSONB(
context,
@ -310,9 +309,17 @@ public interface JSONB {
0,
jsonbBytes.length)
) {
ObjectReader objectReader = provider.getObjectReader(Object.class, fieldBased);
Object object = reader.readAny();
if (reader.resolveTasks != null) {
reader.handleResolveTasks(object);
}
return object;
}
}
Object object = objectReader.readJSONBObject(reader, null, null, 0);
static Object parse(InputStream in, JSONReader.Context context) {
try (JSONReaderJSONB reader = new JSONReaderJSONB(context, in)) {
Object object = reader.readAny();
if (reader.resolveTasks != null) {
reader.handleResolveTasks(object);
}
@ -323,7 +330,6 @@ public interface JSONB {
static Object parse(byte[] jsonbBytes, SymbolTable symbolTable, JSONReader.Feature... features) {
ObjectReaderProvider provider = defaultObjectReaderProvider;
JSONReader.Context context = new JSONReader.Context(provider, symbolTable, features);
boolean fieldBased = (context.features & JSONReader.Feature.FieldBased.mask) != 0;
try (JSONReaderJSONB reader = new JSONReaderJSONB(
context,
@ -331,9 +337,7 @@ public interface JSONB {
0,
jsonbBytes.length)
) {
ObjectReader objectReader = provider.getObjectReader(Object.class, fieldBased);
Object object = objectReader.readJSONBObject(reader, null, null, 0);
Object object = reader.readAny();
if (reader.resolveTasks != null) {
reader.handleResolveTasks(object);
}
@ -371,6 +375,16 @@ public interface JSONB {
}
}
static JSONObject parseObject(InputStream in, JSONReader.Context context) {
try (JSONReaderJSONB reader = new JSONReaderJSONB(context, in)) {
JSONObject object = (JSONObject) reader.readObject();
if (reader.resolveTasks != null) {
reader.handleResolveTasks(object);
}
return object;
}
}
static JSONArray parseArray(byte[] jsonbBytes) {
try (JSONReaderJSONB reader = new JSONReaderJSONB(
new JSONReader.Context(JSONFactory.defaultObjectReaderProvider),
@ -386,6 +400,16 @@ public interface JSONB {
}
}
static JSONArray parseArray(InputStream in, JSONReader.Context context) {
try (JSONReaderJSONB reader = new JSONReaderJSONB(context, in)) {
JSONArray array = (JSONArray) reader.readArray();
if (reader.resolveTasks != null) {
reader.handleResolveTasks(array);
}
return array;
}
}
static <T> List<T> parseArray(byte[] jsonbBytes, Type type) {
if (jsonbBytes == null || jsonbBytes.length == 0) {
return null;

View File

@ -2904,6 +2904,10 @@ public abstract class JSONReader
return new JSONReaderUTF16(context, is);
}
if (charset == StandardCharsets.US_ASCII) {
return new JSONReaderASCII(context, is);
}
throw new JSONException("not support charset " + charset);
}

View File

@ -3,6 +3,7 @@ package com.alibaba.fastjson2;
import com.alibaba.fastjson2.util.*;
import sun.misc.Unsafe;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import static com.alibaba.fastjson2.JSONFactory.*;
@ -18,6 +19,12 @@ final class JSONReaderASCII
nameAscii = true;
}
JSONReaderASCII(Context ctx, InputStream is) {
super(ctx, is);
nameAscii = true;
str = null;
}
@Override
public void next() {
int offset = this.offset;

View File

@ -1,11 +1,10 @@
package com.alibaba.fastjson2.features;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONB;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.*;
import org.junit.jupiter.api.Test;
import java.io.ByteArrayInputStream;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -25,13 +24,92 @@ public class TrimStringTest {
.getString("value"));
assertEquals("a b",
JSON.parseObject(utf8Bytes, 0, utf8Bytes.length, StandardCharsets.US_ASCII, JSONReader.Feature.TrimString)
.getString("value"));
JSON.parseObject(
utf8Bytes, 0, utf8Bytes.length, StandardCharsets.US_ASCII, JSONReader.Feature.TrimString
).getString("value")
);
assertEquals("a b",
JSON.parseObject(
new ByteArrayInputStream(utf8Bytes),
StandardCharsets.US_ASCII,
new JSONReader.Context(JSONReader.Feature.TrimString)
).getString("value")
);
assertEquals("a b",
((JSONObject) JSON.parse(
new ByteArrayInputStream(utf8Bytes),
new JSONReader.Context(JSONReader.Feature.TrimString)
)).getString("value")
);
assertEquals("a b",
JSON.parseObject(
new ByteArrayInputStream(utf8Bytes),
StandardCharsets.US_ASCII,
Bean.class,
new JSONReader.Context(JSONReader.Feature.TrimString)
).value
);
assertEquals("a b",
((Bean) JSON.parseObject(
new ByteArrayInputStream(utf8Bytes),
StandardCharsets.US_ASCII,
(Type) Bean.class,
new JSONReader.Context(JSONReader.Feature.TrimString)
)).value
);
assertEquals("a b",
JSON.parseArray(
new ByteArrayInputStream("[\" a b \"]".getBytes(StandardCharsets.UTF_8)),
StandardCharsets.US_ASCII,
new JSONReader.Context(JSONReader.Feature.TrimString)
).get(0)
);
}
@Test
public void testJSONB() {
byte[] jsonbBytes = JSONObject.of("value", " a b ").toJSONBBytes();
assertEquals("a b", JSONB.parseObject(jsonbBytes, JSONReader.Feature.TrimString).getString("value"));
String result = "a b";
assertEquals(
result,
JSONB.parseObject(
new ByteArrayInputStream(jsonbBytes),
new JSONReader.Context(JSONReader.Feature.TrimString)
).getString("value")
);
assertEquals(
result,
((JSONObject) JSONB.parse(
jsonbBytes,
new JSONReader.Context(JSONReader.Feature.TrimString)
)).getString("value")
);
assertEquals(
result,
JSONB.parseObject(
jsonbBytes,
JSONReader.Feature.TrimString
).getString("value")
);
assertEquals(
result,
((JSONObject) JSONB.parse(
new ByteArrayInputStream(jsonbBytes),
new JSONReader.Context(JSONReader.Feature.TrimString)
)).getString("value")
);
assertEquals(
result,
JSONB.parseArray(
new ByteArrayInputStream(JSONArray.of(" a b ").toJSONBBytes()),
new JSONReader.Context(JSONReader.Feature.TrimString)
).getString(0)
);
}
public static class Bean {
public String value;
}
}