From 3e990599e17bc555a82707e7daa653a793cbfecf Mon Sep 17 00:00:00 2001 From: Tom Dellmann Date: Mon, 30 Dec 2024 22:01:14 +0000 Subject: [PATCH] Add support for unicode toString in JSONWire fixes #934 --- .../net/openhft/chronicle/wire/JSONWire.java | 10 +++ .../net/openhft/chronicle/wire/TextWire.java | 18 +++++ .../net/openhft/chronicle/wire/WireType.java | 22 ++++++- .../wire/JsonWireToStringAcceptanceTest.java | 66 +++++++++++++++++++ 4 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 src/test/java/net/openhft/chronicle/wire/JsonWireToStringAcceptanceTest.java diff --git a/src/main/java/net/openhft/chronicle/wire/JSONWire.java b/src/main/java/net/openhft/chronicle/wire/JSONWire.java index b35f1de701..795a5abeff 100644 --- a/src/main/java/net/openhft/chronicle/wire/JSONWire.java +++ b/src/main/java/net/openhft/chronicle/wire/JSONWire.java @@ -1291,4 +1291,14 @@ public boolean useTypes() { return useTypes; } } + + /** + * Render as a UTF-8 string. + * + * @return a UTF-8 string representation of the wire data. + */ + @Override + public String toString() { + return toUtf8String(); + } } diff --git a/src/main/java/net/openhft/chronicle/wire/TextWire.java b/src/main/java/net/openhft/chronicle/wire/TextWire.java index a6d3a289d5..a6e5ac3510 100644 --- a/src/main/java/net/openhft/chronicle/wire/TextWire.java +++ b/src/main/java/net/openhft/chronicle/wire/TextWire.java @@ -487,6 +487,24 @@ public String toString() { return bytes.toString(); } + /** + * Converts the underlying bytes of this TextWire to its ISO-8859-1 string representation. + * + * @return A string representation of the TextWire's underlying bytes in ISO-8859-1 encoding. + */ + public String to8bitString() { + return bytes.to8bitString(); + } + + /** + * Converts the underlying bytes of this TextWire to its UTF-8 string representation. + * + * @return A string representation of the TextWire's underlying bytes in UTF-8 encoding. + */ + public String toUtf8String() { + return bytes.toUtf8String(); + } + @Override public void copyTo(@NotNull WireOut wire) throws InvalidMarshallableException { if (wire instanceof TextWire || wire instanceof YamlWire) { diff --git a/src/main/java/net/openhft/chronicle/wire/WireType.java b/src/main/java/net/openhft/chronicle/wire/WireType.java index 3c8910febc..ff57b062e2 100644 --- a/src/main/java/net/openhft/chronicle/wire/WireType.java +++ b/src/main/java/net/openhft/chronicle/wire/WireType.java @@ -34,7 +34,6 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.Serializable; -import java.lang.reflect.Constructor; import java.net.URL; import java.util.Map; import java.util.Spliterator; @@ -200,6 +199,11 @@ public Wire apply(@NotNull Bytes bytes) { public boolean isText() { return true; } + + @Override + public String asString(Object marshallable) { + return asUtf8String(marshallable); + } }, JSON_ONLY { @NotNull @@ -212,6 +216,11 @@ public Wire apply(@NotNull Bytes bytes) { public boolean isText() { return true; } + + @Override + public String asString(Object marshallable) { + return asUtf8String(marshallable); + } }, YAML { @SuppressWarnings("deprecation") @@ -282,6 +291,17 @@ public Wire apply(@NotNull Bytes bytes) { // Size after which data is compressed. private static final int COMPRESSED_SIZE = Integer.getInteger("WireType.compressedSize", 128); + protected @NotNull String asUtf8String(Object marshallable) { + ValidatableUtil.startValidateDisabled(); + try (ScopedResource> stlBytes = Wires.acquireBytesScoped()) { + final Bytes bytes = stlBytes.get(); + asBytes(marshallable, bytes); + return bytes.toUtf8String(); + } finally { + ValidatableUtil.endValidateDisabled(); + } + } + /** * Determines the of a given {@link Wire} instance. This method inspects * the underlying type of the provided wire instance and maps it to its corresponding diff --git a/src/test/java/net/openhft/chronicle/wire/JsonWireToStringAcceptanceTest.java b/src/test/java/net/openhft/chronicle/wire/JsonWireToStringAcceptanceTest.java new file mode 100644 index 0000000000..58e040b73b --- /dev/null +++ b/src/test/java/net/openhft/chronicle/wire/JsonWireToStringAcceptanceTest.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2016-2022 chronicle.software + * + * https://chronicle.software + * + * 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 net.openhft.chronicle.wire; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; + +/** + * Verify that unicode characters can be properly represented in JSON output. + */ +public class JsonWireToStringAcceptanceTest { + + private static Collection WIRE_TYPES = Arrays.asList(WireType.JSON, WireType.JSON_ONLY); + + @ParameterizedTest + @ValueSource(strings = {"£", "€", "¥", "₹", "ó", "óaóó", "☞☞☞☞☞", "ÊÆÄ"}) + public void json_verifyAsString(String input) { + Map map = new HashMap<>(); + map.put("x", input); + for (WireType wireType : WIRE_TYPES) { + assertEquals("{\"x\":\"" + input + "\"}", wireType.asString(map)); + } + } + + @ParameterizedTest + @ValueSource(strings = {"£", "€", "¥", "₹", "ó", "óaóó"}) + public void json_verifyObjectToString(String input) { + Map map = new HashMap<>(); + map.put("x", input); + WireOut object = new JSONWire().getValueOut().object(map); + assertEquals("{\"x\":\"" + input + "\"}", object.toString()); + } + + @ParameterizedTest + @ValueSource(strings = {"£", "€", "¥", "₹", "ó", "óaóó"}) + public void json_verifyAsText(String input) { + Map map = new HashMap<>(); + map.put("x", input); + JSONWire jsonWire = new JSONWire(); + jsonWire.getValueOut().object(map); + assertEquals("{\"x\":\"" + input + "\"}", JSONWire.asText(jsonWire)); + } + +} \ No newline at end of file