diff options
author | NARUSE, Yui <nurse@users.noreply.github.com> | 2020-07-31 11:06:58 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-31 11:06:58 +0900 |
commit | 8e081fb05c5054fa575dc9852ec1d599707376c9 (patch) | |
tree | 59914b3a3f83ca424174ba8ff9e211592d1e60d2 /java | |
parent | e7cf232fa71b3a21094497d18c09ee7f24248bc3 (diff) | |
parent | 8a18cf6a14fc1fae54b3d581434a255c9d98ceea (diff) | |
download | json-8e081fb05c5054fa575dc9852ec1d599707376c9.tar.gz |
Merge pull request #405 from Shopify/escape-slash-2.3.0
Add an option to escape forward slash character
Diffstat (limited to 'java')
-rw-r--r-- | java/src/json/ext/Generator.java | 2 | ||||
-rw-r--r-- | java/src/json/ext/GeneratorState.java | 30 | ||||
-rw-r--r-- | java/src/json/ext/StringEncoder.java | 10 |
3 files changed, 39 insertions, 3 deletions
diff --git a/java/src/json/ext/Generator.java b/java/src/json/ext/Generator.java index b5dd73b..914d00e 100644 --- a/java/src/json/ext/Generator.java +++ b/java/src/json/ext/Generator.java @@ -139,7 +139,7 @@ public final class Generator { public StringEncoder getStringEncoder() { if (stringEncoder == null) { - stringEncoder = new StringEncoder(context, getState().asciiOnly()); + stringEncoder = new StringEncoder(context, getState().asciiOnly(), getState().escapeSlash()); } return stringEncoder; } diff --git a/java/src/json/ext/GeneratorState.java b/java/src/json/ext/GeneratorState.java index 44a9311..7fec09d 100644 --- a/java/src/json/ext/GeneratorState.java +++ b/java/src/json/ext/GeneratorState.java @@ -83,6 +83,12 @@ public class GeneratorState extends RubyObject { private boolean quirksMode = DEFAULT_QUIRKS_MODE; static final boolean DEFAULT_QUIRKS_MODE = false; /** + * If set to <code>true</code> the forward slash will be escaped in + * json output. + */ + private boolean escapeSlash = DEFAULT_ESCAPE_SLASH; + static final boolean DEFAULT_ESCAPE_SLASH = false; + /** * The initial buffer length of this state. (This isn't really used on all * non-C implementations.) */ @@ -171,6 +177,9 @@ public class GeneratorState extends RubyObject { * <code>-Infinity</code> should be generated, otherwise an exception is * thrown if these values are encountered. * This options defaults to <code>false</code>. + * <dt><code>:escape_slash</code> + * <dd>set to <code>true</code> if the forward slashes should be escaped + * in the json output (default: <code>false</code>) */ @JRubyMethod(optional=1, visibility=Visibility.PRIVATE) public IRubyObject initialize(ThreadContext context, IRubyObject[] args) { @@ -194,6 +203,7 @@ public class GeneratorState extends RubyObject { this.allowNaN = orig.allowNaN; this.asciiOnly = orig.asciiOnly; this.quirksMode = orig.quirksMode; + this.escapeSlash = orig.escapeSlash; this.bufferInitialLength = orig.bufferInitialLength; this.depth = orig.depth; return this; @@ -346,6 +356,24 @@ public class GeneratorState extends RubyObject { return max_nesting; } + /** + * Returns true if forward slashes are escaped in the json output. + */ + public boolean escapeSlash() { + return escapeSlash; + } + + @JRubyMethod(name="escape_slash") + public RubyBoolean escape_slash_get(ThreadContext context) { + return context.getRuntime().newBoolean(escapeSlash); + } + + @JRubyMethod(name="escape_slash=") + public IRubyObject escape_slash_set(IRubyObject escape_slash) { + escapeSlash = escape_slash.isTrue(); + return escape_slash.getRuntime().newBoolean(escapeSlash); + } + public boolean allowNaN() { return allowNaN; } @@ -430,6 +458,7 @@ public class GeneratorState extends RubyObject { maxNesting = opts.getInt("max_nesting", DEFAULT_MAX_NESTING); allowNaN = opts.getBool("allow_nan", DEFAULT_ALLOW_NAN); asciiOnly = opts.getBool("ascii_only", DEFAULT_ASCII_ONLY); + escapeSlash = opts.getBool("escape_slash", DEFAULT_ESCAPE_SLASH); bufferInitialLength = opts.getInt("buffer_initial_length", DEFAULT_BUFFER_INITIAL_LENGTH); depth = opts.getInt("depth", 0); @@ -457,6 +486,7 @@ public class GeneratorState extends RubyObject { result.op_aset(context, runtime.newSymbol("allow_nan"), allow_nan_p(context)); result.op_aset(context, runtime.newSymbol("ascii_only"), ascii_only_p(context)); result.op_aset(context, runtime.newSymbol("max_nesting"), max_nesting_get(context)); + result.op_aset(context, runtime.newSymbol("escape_slash"), escape_slash_get(context)); result.op_aset(context, runtime.newSymbol("depth"), depth_get(context)); result.op_aset(context, runtime.newSymbol("buffer_initial_length"), buffer_initial_length_get(context)); for (String name: getInstanceVariableNameList()) { diff --git a/java/src/json/ext/StringEncoder.java b/java/src/json/ext/StringEncoder.java index 9d40dd3..26678ed 100644 --- a/java/src/json/ext/StringEncoder.java +++ b/java/src/json/ext/StringEncoder.java @@ -15,7 +15,7 @@ import org.jruby.util.ByteList; * and throws a GeneratorError if any problem is found. */ final class StringEncoder extends ByteListTranscoder { - private final boolean asciiOnly; + private final boolean asciiOnly, escapeSlash; // Escaped characters will reuse this array, to avoid new allocations // or appending them byte-by-byte @@ -37,9 +37,10 @@ final class StringEncoder extends ByteListTranscoder { new byte[] {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; - StringEncoder(ThreadContext context, boolean asciiOnly) { + StringEncoder(ThreadContext context, boolean asciiOnly, boolean escapeSlash) { super(context); this.asciiOnly = asciiOnly; + this.escapeSlash = escapeSlash; } void encode(ByteList src, ByteList out) { @@ -73,6 +74,11 @@ final class StringEncoder extends ByteListTranscoder { case '\b': escapeChar('b'); break; + case '/': + if(escapeSlash) { + escapeChar((char)c); + break; + } default: if (c >= 0x20 && c <= 0x7f || (c >= 0x80 && !asciiOnly)) { |