Author: sseifert Date: Tue May 23 21:03:37 2017 New Revision: 1795961 URL: http://svn.apache.org/viewvc?rev=1795961&view=rev Log: SLING-6872 JCR Content Parser: Support tick as well as double quote when parsing JSON
Added: sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/JsonParserFeature.java (with props) sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/impl/JsonTicksConverter.java (with props) sling/trunk/bundles/jcr/contentparser/src/test/java/org/apache/sling/jcr/contentparser/impl/JsonContentParserTicksTest.java (with props) sling/trunk/bundles/jcr/contentparser/src/test/java/org/apache/sling/jcr/contentparser/impl/JsonTicksConverterTest.java (with props) Modified: sling/trunk/bundles/jcr/contentparser/pom.xml sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/ParserOptions.java sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/impl/JsonContentParser.java sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/package-info.java sling/trunk/bundles/jcr/contentparser/src/test/java/org/apache/sling/jcr/contentparser/impl/JsonContentParserTest.java sling/trunk/bundles/jcr/contentparser/src/test/java/org/apache/sling/jcr/contentparser/impl/TestUtils.java Modified: sling/trunk/bundles/jcr/contentparser/pom.xml URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentparser/pom.xml?rev=1795961&r1=1795960&r2=1795961&view=diff ============================================================================== --- sling/trunk/bundles/jcr/contentparser/pom.xml (original) +++ sling/trunk/bundles/jcr/contentparser/pom.xml Tue May 23 21:03:37 2017 @@ -78,6 +78,12 @@ <scope>compile</scope> </dependency> <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + <version>2.4</version> + <scope>compile</scope> + </dependency> + <dependency> <groupId>org.apache.johnzon</groupId> <artifactId>johnzon-core</artifactId> <version>1.0.0</version> Added: sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/JsonParserFeature.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/JsonParserFeature.java?rev=1795961&view=auto ============================================================================== --- sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/JsonParserFeature.java (added) +++ sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/JsonParserFeature.java Tue May 23 21:03:37 2017 @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.sling.jcr.contentparser; + +/** + * Feature flags for parsing JSON files. + */ +public enum JsonParserFeature { + + /** + * Support comments (/* ... */) in JSON files. + */ + COMMENTS, + + /** + * Support ticks (') additional to double quotes (") as quoting symbol for JSON names and strings. + */ + QUOTE_TICK + +} Propchange: sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/JsonParserFeature.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/JsonParserFeature.java ------------------------------------------------------------------------------ --- svn:keywords (added) +++ svn:keywords Tue May 23 21:03:37 2017 @@ -0,0 +1 @@ +LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author Propchange: sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/JsonParserFeature.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/ParserOptions.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/ParserOptions.java?rev=1795961&r1=1795960&r2=1795961&view=diff ============================================================================== --- sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/ParserOptions.java (original) +++ sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/ParserOptions.java Tue May 23 21:03:37 2017 @@ -20,6 +20,7 @@ package org.apache.sling.jcr.contentpars import java.util.Arrays; import java.util.Collections; +import java.util.EnumSet; import java.util.HashSet; import java.util.Set; @@ -47,11 +48,18 @@ public final class ParserOptions { "jcr:uri:" ))); + /** + * List of JSON parser features activated by default. + */ + public static final EnumSet<JsonParserFeature> DEFAULT_JSON_PARSER_FEATURES + = EnumSet.of(JsonParserFeature.COMMENTS, JsonParserFeature.QUOTE_TICK); + private String defaultPrimaryType = DEFAULT_PRIMARY_TYPE; private boolean detectCalendarValues; private Set<String> ignorePropertyNames; private Set<String> ignoreResourceNames; private Set<String> removePropertyNamePrefixes = DEFAULT_REMOVE_PROPERTY_NAME_PREFIXES; + private EnumSet<JsonParserFeature> jsonParserFeatures = DEFAULT_JSON_PARSER_FEATURES; /** * Default "jcr:primaryType" property for resources that have no explicit value for this value. @@ -121,4 +129,21 @@ public final class ParserOptions { return removePropertyNamePrefixes; } + /** + * Set set of features the JSON parser should apply when parsing files. + * @param value JSON parser features + * @return this + */ + public ParserOptions jsonParserFeatures(EnumSet<JsonParserFeature> value) { + this.jsonParserFeatures = value; + return this; + } + public ParserOptions jsonParserFeatures(JsonParserFeature... value) { + this.jsonParserFeatures = EnumSet.copyOf(Arrays.asList(value)); + return this; + } + public EnumSet<JsonParserFeature> getJsonParserFeatures() { + return jsonParserFeatures; + } + } Modified: sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/impl/JsonContentParser.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/impl/JsonContentParser.java?rev=1795961&r1=1795960&r2=1795961&view=diff ============================================================================== --- sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/impl/JsonContentParser.java (original) +++ sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/impl/JsonContentParser.java Tue May 23 21:03:37 2017 @@ -20,6 +20,7 @@ package org.apache.sling.jcr.contentpars import java.io.IOException; import java.io.InputStream; +import java.io.StringReader; import java.util.Calendar; import java.util.HashMap; import java.util.LinkedHashMap; @@ -35,8 +36,11 @@ import javax.json.JsonString; import javax.json.JsonValue; import javax.json.stream.JsonParsingException; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.CharEncoding; import org.apache.sling.jcr.contentparser.ContentHandler; import org.apache.sling.jcr.contentparser.ContentParser; +import org.apache.sling.jcr.contentparser.JsonParserFeature; import org.apache.sling.jcr.contentparser.ParseException; import org.apache.sling.jcr.contentparser.ParserOptions; @@ -54,21 +58,56 @@ public final class JsonContentParser imp */ private final JsonReaderFactory jsonReaderFactory; + private final boolean jsonQuoteTickets; + public JsonContentParser(ParserOptions options) { this.helper = new ParserHelper(options); - // allow comments in JSON files + Map<String,Object> jsonReaderFactoryConfig = new HashMap<>(); - jsonReaderFactoryConfig.put("org.apache.johnzon.supports-comments", true); + + // allow comments in JSON files? + if (options.getJsonParserFeatures().contains(JsonParserFeature.COMMENTS)) { + jsonReaderFactoryConfig.put("org.apache.johnzon.supports-comments", true); + } + jsonQuoteTickets = options.getJsonParserFeatures().contains(JsonParserFeature.QUOTE_TICK); + jsonReaderFactory = Json.createReaderFactory(jsonReaderFactoryConfig); } @Override public void parse(ContentHandler handler, InputStream is) throws IOException, ParseException { + parse(handler, toJsonObject(is), "/"); + } + + private JsonObject toJsonObject(InputStream is) { + if (jsonQuoteTickets) { + return toJsonObjectWithJsonTicks(is); + } try (JsonReader reader = jsonReaderFactory.createReader(is)) { - parse(handler, reader.readObject(), "/"); + return reader.readObject(); + } + catch (JsonParsingException ex) { + throw new ParseException("Error parsing JSON content: " + ex.getMessage(), ex); + } + } + + private JsonObject toJsonObjectWithJsonTicks(InputStream is) { + String jsonString; + try { + jsonString = IOUtils.toString(is, CharEncoding.UTF_8); + } + catch (IOException ex) { + throw new ParseException("Error getting JSON string.", ex); + } + + // convert ticks to double quotes + jsonString = JsonTicksConverter.tickToDoubleQuote(jsonString); + + try (JsonReader reader = jsonReaderFactory.createReader(new StringReader(jsonString))) { + return reader.readObject(); } catch (JsonParsingException ex) { - throw new ParseException("Error parsing JSON content.", ex); + throw new ParseException("Error parsing JSON content: " + ex.getMessage(), ex); } } Added: sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/impl/JsonTicksConverter.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/impl/JsonTicksConverter.java?rev=1795961&view=auto ============================================================================== --- sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/impl/JsonTicksConverter.java (added) +++ sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/impl/JsonTicksConverter.java Tue May 23 21:03:37 2017 @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.sling.jcr.contentparser.impl; + +/** + * Converts JSON with ticks to JSON with quotes. + * <p>Conversions:</p> + * <ul> + * <li>Converts ticks ' to " when used as quotation marks for names or string values</li> + * <li>Within names or string values quoted with ticks, ticks have to be escaped with <code>\'</code>. + * This escaping sign is removed on the conversion, because in JSON ticks must not be escaped.</li> + * <li>Within names or string values quoted with ticks, double quotes may or may not be escaped. + * After the conversion they are always escaped.</li> + * </ul> + */ +class JsonTicksConverter { + + static String tickToDoubleQuote(final String input) { + final StringBuilder output = new StringBuilder(); + boolean quoted = false; + boolean tickQuoted = false; + boolean escaped = false; + for (int i = 0, len = input.length(); i < len; i++) { + char in = input.charAt(i); + if (quoted || tickQuoted) { + if (escaped) { + if (in != '\'') { + output.append("\\"); + } + escaped = false; + } + else { + if (in == '"') { + if (quoted) { + quoted = false; + } + else if (tickQuoted) { + output.append("\\"); + } + } + else if (in == '\'') { + if (tickQuoted) { + in = '"'; + tickQuoted = false; + } + } + else if (in == '\\') { + escaped = true; + } + } + } + else { + if (in == '\'') { + in = '"'; + tickQuoted = true; + } + else if (in == '"') { + quoted = true; + } + } + if (in == '\\') { + continue; + } + output.append(in); + } + return output.toString(); + } + +} Propchange: sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/impl/JsonTicksConverter.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/impl/JsonTicksConverter.java ------------------------------------------------------------------------------ --- svn:keywords (added) +++ svn:keywords Tue May 23 21:03:37 2017 @@ -0,0 +1 @@ +LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author Propchange: sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/impl/JsonTicksConverter.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/package-info.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/package-info.java?rev=1795961&r1=1795960&r2=1795961&view=diff ============================================================================== --- sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/package-info.java (original) +++ sling/trunk/bundles/jcr/contentparser/src/main/java/org/apache/sling/jcr/contentparser/package-info.java Tue May 23 21:03:37 2017 @@ -19,5 +19,5 @@ /** * Parser for repository content serialized e.g. as JSON or JCR XML. */ -@org.osgi.annotation.versioning.Version("1.1.0") +@org.osgi.annotation.versioning.Version("1.2.0") package org.apache.sling.jcr.contentparser; Modified: sling/trunk/bundles/jcr/contentparser/src/test/java/org/apache/sling/jcr/contentparser/impl/JsonContentParserTest.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentparser/src/test/java/org/apache/sling/jcr/contentparser/impl/JsonContentParserTest.java?rev=1795961&r1=1795960&r2=1795961&view=diff ============================================================================== --- sling/trunk/bundles/jcr/contentparser/src/test/java/org/apache/sling/jcr/contentparser/impl/JsonContentParserTest.java (original) +++ sling/trunk/bundles/jcr/contentparser/src/test/java/org/apache/sling/jcr/contentparser/impl/JsonContentParserTest.java Tue May 23 21:03:37 2017 @@ -27,12 +27,14 @@ import static org.junit.Assert.assertNul import java.io.File; import java.math.BigDecimal; import java.util.Calendar; +import java.util.EnumSet; import java.util.Map; import java.util.TimeZone; import org.apache.sling.jcr.contentparser.ContentParser; import org.apache.sling.jcr.contentparser.ContentParserFactory; import org.apache.sling.jcr.contentparser.ContentType; +import org.apache.sling.jcr.contentparser.JsonParserFeature; import org.apache.sling.jcr.contentparser.ParseException; import org.apache.sling.jcr.contentparser.ParserOptions; import org.apache.sling.jcr.contentparser.impl.mapsupport.ContentElement; @@ -168,4 +170,11 @@ public class JsonContentParserTest { assertNull(invalidChild); } + @Test(expected = ParseException.class) + public void testFailsWithoutCommentsEnabled() throws Exception { + ContentParser underTest = ContentParserFactory.create(ContentType.JSON, + new ParserOptions().jsonParserFeatures(EnumSet.noneOf(JsonParserFeature.class))); + parse(underTest, file); + } + } Added: sling/trunk/bundles/jcr/contentparser/src/test/java/org/apache/sling/jcr/contentparser/impl/JsonContentParserTicksTest.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentparser/src/test/java/org/apache/sling/jcr/contentparser/impl/JsonContentParserTicksTest.java?rev=1795961&view=auto ============================================================================== --- sling/trunk/bundles/jcr/contentparser/src/test/java/org/apache/sling/jcr/contentparser/impl/JsonContentParserTicksTest.java (added) +++ sling/trunk/bundles/jcr/contentparser/src/test/java/org/apache/sling/jcr/contentparser/impl/JsonContentParserTicksTest.java Tue May 23 21:03:37 2017 @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.sling.jcr.contentparser.impl; + +import static org.apache.sling.jcr.contentparser.impl.TestUtils.parse; +import static org.junit.Assert.assertEquals; + +import java.util.EnumSet; +import java.util.Map; + +import org.apache.sling.jcr.contentparser.ContentParser; +import org.apache.sling.jcr.contentparser.ContentParserFactory; +import org.apache.sling.jcr.contentparser.ContentType; +import org.apache.sling.jcr.contentparser.JsonParserFeature; +import org.apache.sling.jcr.contentparser.ParseException; +import org.apache.sling.jcr.contentparser.ParserOptions; +import org.apache.sling.jcr.contentparser.impl.mapsupport.ContentElement; +import org.junit.Before; +import org.junit.Test; + +public class JsonContentParserTicksTest { + + private ContentParser underTest; + + @Before + public void setUp() { + underTest = ContentParserFactory.create(ContentType.JSON, + new ParserOptions().jsonParserFeatures(JsonParserFeature.QUOTE_TICK)); + } + + @Test + public void testJsonWithTicks() throws Exception { + ContentElement content = parse(underTest, "{'prop1':'value1','prop2':123,'obj':{'prop3':'value2'}}"); + + Map<String, Object> props = content.getProperties(); + assertEquals("value1", props.get("prop1")); + assertEquals(123L, props.get("prop2")); + assertEquals("value2", content.getChild("obj").getProperties().get("prop3")); + } + + @Test + public void testJsonWithTicksMixed() throws Exception { + ContentElement content = parse(underTest, "{\"prop1\":'value1','prop2':123,'obj':{'prop3':\"value2\"}}"); + + Map<String, Object> props = content.getProperties(); + assertEquals("value1", props.get("prop1")); + assertEquals(123L, props.get("prop2")); + assertEquals("value2", content.getChild("obj").getProperties().get("prop3")); + } + + @Test + public void testTicksDoubleQuotesInDoubleQuotes() throws Exception { + ContentElement content = parse(underTest, "{\"prop1\":\"'\\\"\'\\\"\"}"); + + Map<String, Object> props = content.getProperties(); + assertEquals("'\"'\"", props.get("prop1")); + } + + @Test + public void testTicksDoubleQuotesInTicks() throws Exception { + ContentElement content = parse(underTest, "{'prop1':'\\'\\\"\\\'\\\"'}"); + + Map<String, Object> props = content.getProperties(); + assertEquals("'\"'\"", props.get("prop1")); + } + + @Test + public void testWithUtf8Escaped() throws Exception { + ContentElement content = parse(underTest, "{\"prop1\":\"\\u03A9\\u03A6\\u00A5\"}"); + + Map<String, Object> props = content.getProperties(); + assertEquals("\u03A9\u03A6\u00A5", props.get("prop1")); + } + + @Test + public void testWithTicksUtf8Escaped() throws Exception { + ContentElement content = parse(underTest, "{'prop1':'\\u03A9\\u03A6\\u00A5'}"); + + Map<String, Object> props = content.getProperties(); + assertEquals("\u03A9\u03A6\u00A5", props.get("prop1")); + } + + @Test(expected = ParseException.class) + public void testFailsWihtoutFeatureEnabled() throws Exception { + underTest = ContentParserFactory.create(ContentType.JSON, + new ParserOptions().jsonParserFeatures(EnumSet.noneOf(JsonParserFeature.class))); + parse(underTest, "{'prop1':'value1','prop2':123,'obj':{'prop3':'value2'}}"); + } + +} Propchange: sling/trunk/bundles/jcr/contentparser/src/test/java/org/apache/sling/jcr/contentparser/impl/JsonContentParserTicksTest.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sling/trunk/bundles/jcr/contentparser/src/test/java/org/apache/sling/jcr/contentparser/impl/JsonContentParserTicksTest.java ------------------------------------------------------------------------------ --- svn:keywords (added) +++ svn:keywords Tue May 23 21:03:37 2017 @@ -0,0 +1 @@ +LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author Propchange: sling/trunk/bundles/jcr/contentparser/src/test/java/org/apache/sling/jcr/contentparser/impl/JsonContentParserTicksTest.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: sling/trunk/bundles/jcr/contentparser/src/test/java/org/apache/sling/jcr/contentparser/impl/JsonTicksConverterTest.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentparser/src/test/java/org/apache/sling/jcr/contentparser/impl/JsonTicksConverterTest.java?rev=1795961&view=auto ============================================================================== --- sling/trunk/bundles/jcr/contentparser/src/test/java/org/apache/sling/jcr/contentparser/impl/JsonTicksConverterTest.java (added) +++ sling/trunk/bundles/jcr/contentparser/src/test/java/org/apache/sling/jcr/contentparser/impl/JsonTicksConverterTest.java Tue May 23 21:03:37 2017 @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.sling.jcr.contentparser.impl; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import static org.apache.sling.jcr.contentparser.impl.JsonTicksConverter.*; + +public class JsonTicksConverterTest { + + @Test + public void testNoConvert() { + assertEquals("{\"p\":\"v\"}", tickToDoubleQuote("{\"p\":\"v\"}")); + } + + @Test + public void testTickToQuote() { + assertEquals("{\"p\":\"v\"}", tickToDoubleQuote("{'p':\"v\"}")); + } + + @Test + public void testTickToQuoteMixed() { + assertEquals("{\"p\":\"v\"}", tickToDoubleQuote("{'p':\"v\"}")); + assertEquals("{\"p\":\"v\"}", tickToDoubleQuote("{\"p\":'v'}")); + } + + @Test + public void testTicksDoubleQuotesInDoubleQuotes() { + assertEquals("{\"p\":\"'\\\"'\\\"\"}", tickToDoubleQuote("{\"p\":\"'\\\"'\\\"\"}")); + } + + @Test + public void testTicksDoubleQuotesInTicks() { + assertEquals("{\"p\":\"'\\\"'\\\"\"}", tickToDoubleQuote("{\"p\":'\\'\\\"\\'\\\"'}")); + assertEquals("{\"p\":\"'\\\"'\\\"\"}", tickToDoubleQuote("{\"p\":'\\'\"\\'\"'}")); + } + + @Test + public void testTickToQuoteWithUtf8Escaped() { + assertEquals("{\"p\":\"\\u03A9\\u03A6\\u00A5\"}", tickToDoubleQuote("{'p':\"\\u03A9\\u03A6\\u00A5\"}")); + } + +} Propchange: sling/trunk/bundles/jcr/contentparser/src/test/java/org/apache/sling/jcr/contentparser/impl/JsonTicksConverterTest.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sling/trunk/bundles/jcr/contentparser/src/test/java/org/apache/sling/jcr/contentparser/impl/JsonTicksConverterTest.java ------------------------------------------------------------------------------ --- svn:keywords (added) +++ svn:keywords Tue May 23 21:03:37 2017 @@ -0,0 +1 @@ +LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author Propchange: sling/trunk/bundles/jcr/contentparser/src/test/java/org/apache/sling/jcr/contentparser/impl/JsonTicksConverterTest.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: sling/trunk/bundles/jcr/contentparser/src/test/java/org/apache/sling/jcr/contentparser/impl/TestUtils.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentparser/src/test/java/org/apache/sling/jcr/contentparser/impl/TestUtils.java?rev=1795961&r1=1795960&r2=1795961&view=diff ============================================================================== --- sling/trunk/bundles/jcr/contentparser/src/test/java/org/apache/sling/jcr/contentparser/impl/TestUtils.java (original) +++ sling/trunk/bundles/jcr/contentparser/src/test/java/org/apache/sling/jcr/contentparser/impl/TestUtils.java Tue May 23 21:03:37 2017 @@ -19,10 +19,12 @@ package org.apache.sling.jcr.contentparser.impl; import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import org.apache.commons.lang3.CharEncoding; import org.apache.sling.jcr.contentparser.ContentParser; import org.apache.sling.jcr.contentparser.impl.mapsupport.ContentElement; import org.apache.sling.jcr.contentparser.impl.mapsupport.ContentElementHandler; @@ -41,5 +43,13 @@ public final class TestUtils { return handler.getRoot(); } } + + public static ContentElement parse(ContentParser contentParser, String jsonContent) throws IOException { + try (ByteArrayInputStream is = new ByteArrayInputStream(jsonContent.getBytes(CharEncoding.UTF_8))) { + ContentElementHandler handler = new ContentElementHandler(); + contentParser.parse(handler, is); + return handler.getRoot(); + } + } }