Skip to content

Commit

Permalink
[Feature] add a DisableSingleQuote flag for JsonReader (#2909)
Browse files Browse the repository at this point in the history
* add support to disable single quote ondemand

* update doc for disable single quote

* fix checkstyle
  • Loading branch information
wyTrivail committed Aug 30, 2024
1 parent c9b2559 commit 9f631cd
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 2 deletions.
10 changes: 9 additions & 1 deletion core/src/main/java/com/alibaba/fastjson2/JSONReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -1974,6 +1974,9 @@ public void read(Map object, ObjectReader itemReader, long features) {
}

public void read(Map object, long features) {
if (ch == '\'' && ((context.features & Feature.DisableSingleQuote.mask) != 0)) {
throw notSupportName();
}
if ((ch == '"' || ch == '\'') && !typeRedirect) {
String str = readString();
if (str.isEmpty()) {
Expand Down Expand Up @@ -4555,7 +4558,12 @@ public enum Feature {
*
* @since 2.0.51
*/
UseLongForInts(1 << 30);
UseLongForInts(1 << 30),

/**
* Feature that disables the support for single quote.
*/
DisableSingleQuote(1 << 31);

public final long mask;

Expand Down
6 changes: 6 additions & 0 deletions core/src/main/java/com/alibaba/fastjson2/JSONReaderASCII.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ public final boolean nextIfNullOrEmptyString() {
public final long readFieldNameHashCode() {
final byte[] bytes = this.bytes;
int ch = this.ch;
if (ch == '\'' && ((context.features & Feature.DisableSingleQuote.mask) != 0)) {
throw notSupportName();
}
if (ch != '"' && ch != '\'') {
if ((context.features & Feature.AllowUnQuotedFieldNames.mask) != 0 && isFirstIdentifier(ch)) {
return readFieldNameHashCodeUnquote();
Expand Down Expand Up @@ -1015,6 +1018,9 @@ public final String getFieldName() {
@Override
public final String readFieldName() {
final char quote = ch;
if (quote == '\'' && ((context.features & Feature.DisableSingleQuote.mask) != 0)) {
throw notSupportName();
}
if (quote != '"' && quote != '\'') {
if ((context.features & Feature.AllowUnQuotedFieldNames.mask) != 0 && isFirstIdentifier(quote)) {
return readFieldNameUnquote();
Expand Down
10 changes: 10 additions & 0 deletions core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF16.java
Original file line number Diff line number Diff line change
Expand Up @@ -1109,6 +1109,9 @@ public final long readFieldNameHashCodeUnquote() {
@Override
public final long readFieldNameHashCode() {
final char[] chars = this.chars;
if (ch == '\'' && ((context.features & Feature.DisableSingleQuote.mask) != 0)) {
throw notSupportName();
}
if (ch != '"' && ch != '\'') {
if ((context.features & Feature.AllowUnQuotedFieldNames.mask) != 0 && isFirstIdentifier(ch)) {
return readFieldNameHashCodeUnquote();
Expand Down Expand Up @@ -1738,6 +1741,9 @@ public final String getFieldName() {
@Override
public final String readFieldName() {
final char quote = ch;
if (quote == '\'' && ((context.features & Feature.DisableSingleQuote.mask) != 0)) {
throw notSupportName();
}
if (quote != '"' && quote != '\'') {
if ((context.features & Feature.AllowUnQuotedFieldNames.mask) != 0 && isFirstIdentifier(quote)) {
return readFieldNameUnquote();
Expand Down Expand Up @@ -2317,6 +2323,10 @@ public final String readFieldName() {
@Override
public final boolean skipName() {
char quote = ch;
if (quote == '\'' && ((context.features & Feature.DisableSingleQuote.mask) != 0)) {
throw notSupportName();
}

if (quote != '"' && quote != '\'') {
if ((context.features & Feature.AllowUnQuotedFieldNames.mask) != 0) {
readFieldNameHashCodeUnquote();
Expand Down
9 changes: 9 additions & 0 deletions core/src/main/java/com/alibaba/fastjson2/JSONReaderUTF8.java
Original file line number Diff line number Diff line change
Expand Up @@ -2323,6 +2323,9 @@ public final boolean nextIfValue4Match11(long name1) {
public long readFieldNameHashCode() {
final byte[] bytes = this.bytes;
int ch = this.ch;
if (ch == '\'' && ((context.features & Feature.DisableSingleQuote.mask) != 0)) {
throw notSupportName();
}
if (ch != '"' && ch != '\'') {
if ((context.features & Feature.AllowUnQuotedFieldNames.mask) != 0 && isFirstIdentifier(ch)) {
return readFieldNameHashCodeUnquote();
Expand Down Expand Up @@ -3127,6 +3130,9 @@ public String getFieldName() {
@Override
public String readFieldName() {
final char quote = ch;
if (quote == '\'' && ((context.features & Feature.DisableSingleQuote.mask) != 0)) {
throw notSupportName();
}
if (quote != '"' && quote != '\'') {
if ((context.features & Feature.AllowUnQuotedFieldNames.mask) != 0 && isFirstIdentifier(quote)) {
return readFieldNameUnquote();
Expand Down Expand Up @@ -4693,6 +4699,9 @@ protected void readString0() {
@Override
public final boolean skipName() {
char quote = ch;
if (quote == '\'' && ((context.features & Feature.DisableSingleQuote.mask) != 0)) {
throw notSupportName();
}
if (quote != '"' && quote != '\'') {
if ((context.features & Feature.AllowUnQuotedFieldNames.mask) != 0) {
readFieldNameHashCodeUnquote();
Expand Down
1 change: 1 addition & 0 deletions core/src/test/java/com/alibaba/fastjson2/JSONTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -1209,6 +1209,7 @@ public void isValid1() {
assertFalse(JSON.isValid("{", JSONReader.Feature.AllowUnQuotedFieldNames));
assertFalse(JSON.isValid("\"", JSONReader.Feature.AllowUnQuotedFieldNames));
assertFalse(JSON.isValid("'", JSONReader.Feature.AllowUnQuotedFieldNames));
assertFalse(JSON.isValid("'", JSONReader.Feature.DisableSingleQuote));
}

@Test
Expand Down
11 changes: 11 additions & 0 deletions core/src/test/java/com/alibaba/fastjson2/read/ObjectKeyTest.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.alibaba.fastjson2.read;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONException;
import com.alibaba.fastjson2.JSONReader;
import org.junit.jupiter.api.Test;

Expand All @@ -9,6 +10,7 @@
import java.util.Map;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

public class ObjectKeyTest {
@Test
Expand All @@ -31,6 +33,15 @@ public void test1() {
assertEquals(1, ((Bean) JSON.parseObject(s.toCharArray(), (Type) Bean.class, JSONReader.Feature.AllowUnQuotedFieldNames)).items.size());
}

@Test
public void testDisablingSingleQuote() {
String str = "{'key': 'value'}";
byte[] bytes = str.getBytes();
assertThrows(JSONException.class, () -> {
JSON.parseObject(bytes, 0, bytes.length, StandardCharsets.UTF_8, Bean.class, JSONReader.Feature.DisableSingleQuote);
});
}

public static class Bean {
public Map<String, Item> items;
}
Expand Down
2 changes: 1 addition & 1 deletion docs/features_cn.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class Model {
| AllowUnQuotedFieldNames | 支持不带双引号的字段名 |
| NonStringKeyAsString | 非String类型的Key当做String处理 |
| Base64StringAsByteArray | 将byte[]序列化为Base64格式的字符串 |

| DisableSingleQuote | Do not allow single quote on key and value
# 5. JSONWriter.Feature介绍

| JSONWriter.Feature | 介绍 |
Expand Down
2 changes: 2 additions & 0 deletions docs/features_en.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ class Model {
| AllowUnQuotedFieldNames | |
| NonStringKeyAsString | |
| Base64StringAsByteArray | |
| DisableSingleQuote | Do not allow single quote in key name and values.

# 5. JSONWriter.Feature

| JSONWriter.Feature | Description |
Expand Down

0 comments on commit 9f631cd

Please sign in to comment.