package org.example;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import javax.json.Json;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParser.Event;
public class EJsonReader {
@SuppressWarnings("unchecked")
public static Map<String, Object> parseObject(String json) {
return (Map<String, Object>) parse(json);
}
@SuppressWarnings("unchecked")
public static List<Object> parseList(String json) {
return (List<Object>) parse(json);
}
public static Object parse(String json) {
return parse(new StringReader(json));
}
public static Object parse(Reader reader) {
return parse(Json.createParser(reader));
}
public static Object parse(JsonParser parser) {
return new EJsonReader(parser).parseJson();
}
private final JsonParser parser;
private final Stack stack = new Stack();
private Context currentContext;
EJsonReader(JsonParser parser) {
this.parser = parser;
}
private void startArray() {
stack.push(currentContext);
currentContext = new ArrayContext();
}
private void startObject() {
stack.push(currentContext);
currentContext = new ObjectContext();
}
private void endArray() {
end();
}
private void endObject() {
end();
}
private void end() {
if (!stack.isEmpty()) {
currentContext = stack.pop();
}
}
private void setValue(Object value) {
currentContext.setValue(value);
}
private void setValueNull() {
currentContext.setValueNull();
}
private Object parseJson() {
while (parser.hasNext()) {
Event event = parser.next();
switch (event) {
case START_ARRAY:
startArray();
break;
case START_OBJECT:
startObject();
break;
case KEY_NAME:
currentContext.setKey(parser.getString());
break;
case VALUE_STRING:
setValue(parser.getString());
break;
case VALUE_NUMBER:
if (parser.isIntegralNumber()) {
setValue(parser.getLong());
} else {
setValue(parser.getBigDecimal());
}
break;
case VALUE_TRUE:
setValue(Boolean.TRUE);
break;
case VALUE_FALSE:
setValue(Boolean.FALSE);
break;
case VALUE_NULL:
setValueNull();
break;
case END_OBJECT:
endObject();
break;
case END_ARRAY:
endArray();
break;
default:
break;
}
}
return currentContext.getValue();
}
private static final class Stack {
private Context head;
private void push(Context context) {
if (context != null) {
context.next = head;
head = context;
}
}
private Context pop() {
if (head == null) {
throw new NoSuchElementException();
}
Context temp = head;
head = head.next;
return temp;
}
private boolean isEmpty() {
return head == null;
}
}
private static abstract class Context {
Context next;
abstract Object getValue();
abstract void setKey(String key);
abstract void setValue(Object value);
abstract void setValueNull();
// abstract Event getNextEvent();
}
private static class ObjectContext extends Context {
private String key;
Map<String, Object> map = new LinkedHashMap<>();
Object getValue() {
return map;
}
public void setKey(String key) {
this.key = key;
}
void setValue(Object value) {
map.put(key, value);
}
void setValueNull() {
map.put(key, null);
}
}
private static class ArrayContext extends Context {
List<Object> values = new ArrayList<>();
Object getValue() {
return values;
}
void setValue(Object value) {
values.add(value);
}
void setValueNull() {
}
void setKey(String key) {
}
}
}