use buffered reader, assume always UTF-8, fix toMap() convenience

This commit is contained in:
Jörg Prante 2021-10-18 09:20:37 +02:00
parent 9759d5c020
commit 9f584c4c7a
9 changed files with 133 additions and 24 deletions

View file

@ -7,7 +7,10 @@ import org.xbib.datastructures.api.Generator;
import org.xbib.datastructures.api.Node;
import org.xbib.datastructures.api.Parser;
import org.xbib.datastructures.api.TimeValue;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.time.Instant;
@ -35,9 +38,15 @@ public class Json implements DataStructure {
this.separator = separator;
}
@SuppressWarnings("unchecked")
public static Map<String, Object> toMap(String yaml) throws IOException {
return (Map<String, Object>) INSTANCE.createParser().parse(new StringReader(yaml)).get();
public static Map<String, Object> toMap(String json) throws IOException {
return toMap(new StringReader(json));
}
public static Map<String, Object> toMap(Reader reader) throws IOException {
// buffered reader is required for mark() support
try (BufferedReader bufferedReader = new BufferedReader(reader)){
return JsonGenerator.toMap(INSTANCE.createParser().parse(bufferedReader));
}
}
public static String toString(Map<String, Object> map) throws IOException {

View file

@ -263,16 +263,16 @@ public class JsonBuilder implements Builder {
int l = string.length();
for (int i = 0; i < l; i++) {
char c = string.charAt(i);
if (c == '"' || c < 32 || c >= 127 || c == '\\') {
if (start < i) {
sb.append(string, start, i - start);
if (c == '"' || c == '\\' || c < 32) {
if (i > start) {
sb.append(string, start, i);
}
start = i;
start = i + 1;
sb.append(escapeCharacter(c));
}
}
if (start < l) {
sb.append(string, start, l - start);
if (l > start) {
sb.append(string, start, l);
}
sb.append('"');
return sb;

View file

@ -2,6 +2,8 @@ package org.xbib.datastructures.json.tiny;
import org.xbib.datastructures.api.Generator;
import org.xbib.datastructures.api.Node;
import org.xbib.datastructures.tiny.TinyList;
import org.xbib.datastructures.tiny.TinyMap;
import java.io.IOException;
import java.io.Writer;
@ -27,6 +29,11 @@ public class JsonGenerator implements Generator {
}
}
@SuppressWarnings("unchecked")
public static Map<String, Object> toMap(Node<?> root) {
return (Map<String, Object>) internalMap(root);
}
private void internalWrite(Node<?> curnode) throws IOException {
if (curnode instanceof ValueNode) {
ValueNode valueNode = (ValueNode) curnode;
@ -49,4 +56,27 @@ public class JsonGenerator implements Generator {
builder.endCollection();
}
}
private static Object internalMap(Node<?> curnode) {
if (curnode instanceof ValueNode) {
ValueNode valueNode = (ValueNode) curnode;
return valueNode.get();
} else if (curnode instanceof MapNode) {
MapNode mapNode = (MapNode) curnode;
TinyMap.Builder<String, Object> map = TinyMap.builder();
for (Map.Entry<CharSequence, Node<?>> e : mapNode.get().entrySet()) {
map.put(e.getKey().toString(), internalMap(e.getValue()));
}
return map.build();
} else if (curnode instanceof ListNode) {
ListNode listNode = (ListNode) curnode;
TinyList.Builder<Object> list = TinyList.builder();
for (Node<?> node : listNode.get()) {
list.add(internalMap(node));
}
return list.build();
} else {
return null;
}
}
}

View file

@ -1,6 +1,7 @@
package org.xbib.datastructures.json.tiny.test;
import org.junit.jupiter.api.Test;
import org.xbib.datastructures.json.tiny.Json;
import org.xbib.datastructures.json.tiny.JsonBuilder;
import org.xbib.datastructures.json.tiny.StreamParser;
@ -11,9 +12,17 @@ import java.util.List;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class JsonBuilderTest {
@Test
public void testUmlautEncoding() throws IOException{
JsonBuilder jsonBuilder = new JsonBuilder();
jsonBuilder.buildMap(Map.of("Hello", "Jörg"));
assertEquals("{\"Hello\":\"Jörg\"}", jsonBuilder.build());
}
@Test
public void testObjectStrFromMap() throws IOException {
JsonBuilder jsonBuilder = new JsonBuilder();
@ -213,4 +222,11 @@ public class JsonBuilderTest {
assertEquals("[{\"a\":\"b\"},{\"c\":\"d\"}]", jsonBuilder.build());
}
@SuppressWarnings("unchecked")
@Test
public void testJsonToMap() throws IOException {
Map<String, Object> map = Json.toMap("{\"map\":{\"a\":\"b\"}}");
assertTrue(map.get("map") instanceof Map);
assertEquals("b", ((Map<String, Object>) map.get("map")).get("a"));
}
}

View file

@ -9,29 +9,33 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.logging.Level;
import java.util.logging.Logger;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class ParserTest {
@Test
public void testStringParser() throws IOException {
try (InputStream inputStream = ParserTest.class.getResourceAsStream("/org/xbib/datastructures/json/tiny/test/test.json")) {
byte [] b = inputStream.readAllBytes();
String string = new String(b, StandardCharsets.UTF_8);
StringParser stringParser = new StringParser(new TinyJsonListener());
stringParser.parse(string);
Logger.getLogger("").log(Level.INFO, stringParser.getNode().get().toString());
stringParser.parse(string);
Logger.getLogger("").log(Level.INFO, stringParser.getNode().get().toString());
if (inputStream != null) {
byte[] b = inputStream.readAllBytes();
String string = new String(b, StandardCharsets.UTF_8);
StringParser stringParser = new StringParser(new TinyJsonListener());
stringParser.parse(string);
assertEquals("{a=b, c=d, e=[f, g], h={i={j=k}}, l=null, m=true, n=false, o=0, p=1, q=-1, r=0.0, s=1.0, t=2.1, u=-1.0, v=-2.1, w=, x=₫, y=Jörg}",
stringParser.getNode().get().toString());
}
}
}
@Test
public void testStreamParser() throws IOException {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(ParserTest.class.getResourceAsStream("/org/xbib/datastructures/json/tiny/test/test.json")))) {
StreamParser streamParser = new StreamParser(new TinyJsonListener());
Logger.getLogger("").log(Level.INFO, streamParser.parse(reader).get().toString());
InputStream inputStream = ParserTest.class.getResourceAsStream("/org/xbib/datastructures/json/tiny/test/test.json");
if (inputStream != null) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
StreamParser streamParser = new StreamParser(new TinyJsonListener());
assertEquals("{a=b, c=d, e=[f, g], h={i={j=k}}, l=null, m=true, n=false, o=0, p=1, q=-1, r=0.0, s=1.0, t=2.1, u=-1.0, v=-2.1, w=, x=₫, y=Jörg}", streamParser.parse(reader).get().toString());
}
}
}
}

View file

@ -19,5 +19,6 @@
"u": -1.0,
"v": -2.1,
"w": "",
"x": "\u20AB"
"x": "\u20AB",
"y": "Jörg"
}

View file

@ -3,7 +3,9 @@ package org.xbib.datastructures.yaml.tiny;
import org.xbib.datastructures.api.*;
import org.xbib.datastructures.api.Builder;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.time.Instant;
@ -31,9 +33,15 @@ public class Yaml implements DataStructure {
this.separator = separator;
}
@SuppressWarnings("unchecked")
public static Map<String, Object> toMap(String yaml) throws IOException {
return (Map<String, Object>) INSTANCE.createParser().parse(new StringReader(yaml)).get();
return toMap(new StringReader(yaml));
}
public static Map<String, Object> toMap(Reader reader) throws IOException {
// buffered reader is required for mark() support
try (BufferedReader bufferedReader = new BufferedReader(reader)){
return YamlGenerator.toMap(INSTANCE.createParser().parse(bufferedReader));
}
}
public static String toString(Map<String, Object> map) throws IOException {

View file

@ -2,6 +2,8 @@ package org.xbib.datastructures.yaml.tiny;
import org.xbib.datastructures.api.Generator;
import org.xbib.datastructures.api.Node;
import org.xbib.datastructures.tiny.TinyList;
import org.xbib.datastructures.tiny.TinyMap;
import java.io.IOException;
import java.io.StringWriter;
@ -27,6 +29,11 @@ public class YamlGenerator implements Generator {
this.indent = indent;
}
@SuppressWarnings("unchecked")
public static Map<String, Object> toMap(Node<?> root) {
return (Map<String, Object>) internalMap(root);
}
@Override
public void generate(Writer writer) throws IOException {
this.writer = writer;
@ -156,4 +163,28 @@ public class YamlGenerator implements Generator {
}
return sb.toString();
}
private static Object internalMap(Node<?> curnode) {
if (curnode instanceof ValueNode) {
ValueNode valueNode = (ValueNode) curnode;
return valueNode.get();
} else if (curnode instanceof MapNode) {
MapNode mapNode = (MapNode) curnode;
TinyMap.Builder<String, Object> map = TinyMap.builder();
for (Map.Entry<CharSequence, Node<?>> e : mapNode.get().entrySet()) {
map.put(e.getKey().toString(), internalMap(e.getValue()));
}
return map.build();
} else if (curnode instanceof ListNode) {
ListNode listNode = (ListNode) curnode;
TinyList.Builder<Object> list = TinyList.builder();
for (Node<?> node : listNode.get()) {
list.add(internalMap(node));
}
return list.build();
} else {
return null;
}
}
}

View file

@ -6,10 +6,12 @@ import org.xbib.datastructures.api.DataStructure;
import org.xbib.datastructures.tiny.TinyMap;
import org.xbib.datastructures.yaml.tiny.Yaml;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class YamlBuilderTest {
@ -104,4 +106,12 @@ public class YamlBuilderTest {
"- e: f\n" +
" g: h\n", builder.build());
}
@SuppressWarnings("unchecked")
@Test
public void testYamlToMap() throws IOException {
Map<String, Object> map = Yaml.toMap("map:\n a: b\n");
assertTrue(map.get("map") instanceof Map);
assertEquals("b", ((Map<String, Object>) map.get("map")).get("a"));
}
}