繁体   English   中英

将带有特殊字符的字符串转换为 JSONObject

[英]Convert string with special characters to JSONObject

我的输入字符串为"{"notes_text": "someString"}" someString 可以包含 \ 或 "。我需要创建一个 JSONObject 来表示这个字符串。

如果它包含特殊字符,只需使用将字符串作为输入的构造函数将引发异常。

我已经尝试了几种方法来做到这一点

  • 使用库来转义字符 - 例如,这将导致"{\"notes_text\":\"\"\"}""{\"notes_text\":\"\\\"}" 。我需要将它们分别更改为"{\"notes_text\":\"\\\"\"}""{\"notes_text\":\"\\\\\"}"否则它会在转换为 JSON Object 时再次抛出异常。 在字符串中使用 replace 方法将转换输入字符串中的所有 \"
  • 不要转义输入字符串中的特殊字符并使用字符串替换方法将\转换为\和“到\”。 但这将再次替换输入字符串中的所有双引号

我尝试使用正则表达式,但无法str.replaceAll("\\\".*\\\".*\\\"", replacemntString)中的替换字符串

课程

这是解决 json 损坏的初始问题的两个类:

public class FixedJson {

    private final String target;

    private final Pattern pattern;

    public FixedJson(String target) {
        this(
            target,
            Pattern.compile("\"(.+?)\"[^\\w\"]")
        );
    }

    public FixedJson(String target, Pattern pattern) {
        this.target = target;
        this.pattern = pattern;
    }

    public String value() {
        return this.pattern.matcher(this.target).replaceAll(
            matchResult -> {
                StringBuilder sb = new StringBuilder();
                sb.append(
                    matchResult.group(),
                    0,
                    matchResult.start(1) - matchResult.start(0)
                );
                sb.append(
                    new Escaped(
                        new Escaped(matchResult.group(1)).value()
                    ).value()
                );
                sb.append(
                    matchResult.group().substring(
                        matchResult.group().length() - (matchResult.end(0) - matchResult.end(1))
                    )
                );
                return sb.toString();
            }
        );
    }
}
public class Escaped {

    private final String target;

    private final Pattern pattern;

    public Escaped(String target) {
        this(
            target,
            Pattern.compile("[\\\\\"]")
        );
    }

    public Escaped(String target, Pattern pattern) {
        this.target = target;
        this.pattern = pattern;
    }

    public String value() {
        return this.pattern
            .matcher(this.target)
            .replaceAll("\\\\$0");
    }
}

单元测试

我已经编写了单元测试来证明正确性:

import java.util.regex.Pattern;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;

public class FixedJsonTest {

    @Test
    public void normalValue() {
        assertEquals(
            "{\"notes_text\": \"someString\"}",
            new FixedJson("{\"notes_text\": \"someString\"}").value()
        );
    }

    @Test
    public void valueWithOneDoubleQuotes() {
        assertEquals(
            "{\"notes_text\": \"\\\"\"}",
            new FixedJson("{\"notes_text\": \"\"\"}").value()
        );
    }

    @Test
    public void valueWithOneDoubleQuotesAndAnotherValue() {
        assertEquals(
            "{\"notes_text\": \"\\\"\", \"hello\": \"world\"}",
            new FixedJson("{\"notes_text\": \"\"\", \"hello\": \"world\"}").value()
        );
    }

    @Test
    public void valueWithTwoDoubleQuotes() {
        assertEquals(
            "{\"notes_text\": \"\\\"\\\"\"}",
            new FixedJson("{\"notes_text\": \"\"\"\"}").value()
        );
    }

    @Test
    public void valueWithTwoDoubleQuotesAndAnotherValue() {
        assertEquals(
            "{\"notes_text\": \"\\\"\\\"\", \"hello\": \"world\"}",
            new FixedJson("{\"notes_text\": \"\"\"\", \"hello\": \"world\"}").value()
        );
    }

    @Test
    public void valueWithOneSlash() {
        assertEquals(
            "{\"notes_text\": \"\\\\\"}",
            new FixedJson("{\"notes_text\": \"\\\"}").value()
        );
    }

    @Test
    public void valueWithOneSlashAndAnotherValue() {
        assertEquals(
            "{\"notes_text\": \"\\\\\", \"hello\": \"world\"}",
            new FixedJson("{\"notes_text\": \"\\\", \"hello\": \"world\"}").value()
        );
    }

    @Test
    public void valueWithTwoSlashes() {
        assertEquals(
            "{\"notes_text\": \"\\\\\\\\\"}",
            new FixedJson("{\"notes_text\": \"\\\\\"}").value()
        );
    }

    @Test
    public void valueWithTwoSlashesAndAnotherValue() {
        assertEquals(
            "{\"notes_text\": \"\\\\\\\\\", \"hello\": \"world\"}",
            new FixedJson("{\"notes_text\": \"\\\\\", \"hello\": \"world\"}").value()
        );
    }
}
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;

public class EscapedTest {

    @Test
    public void doubleQuotesTest() {
        assertEquals(
            new Escaped("\"").value(),
            "\\\""
        );
        assertEquals(
            new Escaped("abc\"def").value(),
            "abc\\\"def"
        );
    }

    @Test
    public void slashesTest() {
        assertEquals(
            new Escaped("\\").value(),
            "\\\\"
        );
        assertEquals(
            new Escaped("abc\\def").value(),
            "abc\\\\def"
        );
    }

    @Test
    public void mixedTest() {
        assertEquals(
            new Escaped("\\\"").value(),
            "\\\\\\\""
        );
        assertEquals(
            new Escaped("abc\\\"def").value(),
            "abc\\\\\\\"def"
        );
    }
}

完整的工作示例

import java.util.regex.Pattern;

public class FixedJsonExample {
    public static void main(String[] args) {
        String invalidJson = "{\"notes_text\":\"\"\"}";

        final String fixedJson = new FixedJson(invalidJson).value();
        System.out.println("fixedJson = " + fixedJson);
    }


    public static class FixedJson {

        private final String target;

        private final Pattern pattern;

        public FixedJson(String target) {
            this(
                target,
                Pattern.compile("\"(.+?)\"[^\\w\"]")
            );
        }

        public FixedJson(String target, Pattern pattern) {
            this.target = target;
            this.pattern = pattern;
        }

        public String value() {
            return this.pattern.matcher(this.target).replaceAll(
                matchResult -> {
                    StringBuilder sb = new StringBuilder();
                    sb.append(
                        matchResult.group(),
                        0,
                        matchResult.start(1) - matchResult.start(0)
                    );
                    sb.append(
                        new Escaped(
                            new Escaped(matchResult.group(1)).value()
                        ).value()
                    );
                    sb.append(
                        matchResult.group().substring(
                            matchResult.group().length() - (matchResult.end(0) - matchResult.end(1))
                        )
                    );
                    return sb.toString();
                }
            );
        }
    }

    public static class Escaped {

        private final String target;

        private final Pattern pattern;

        public Escaped(String target) {
            this(
                target,
                Pattern.compile("[\\\\\"]")
            );
        }

        public Escaped(String target, Pattern pattern) {
            this.target = target;
            this.pattern = pattern;
        }

        public String value() {
            return this.pattern
                .matcher(this.target)
                .replaceAll("\\\\$0");
        }
    }
}

及其标准输出:

fixedJson = {"notes_text":"\""}

此 JSON 可以使用以下工具进行验证: https://jsonlint.com/

正则表达式解释

FixedJson

第一个 class FixedJson使用正则表达式匹配 JSON 引理:双引号之间的所有内容(包括放错位置的双引号)。

有关更多详细信息,请参见此处的交互式示例: https://regexr.com/54blf

Escaped class

第二个 class Escaped使用正则表达式来匹配斜杠或双引号。 他们的 escaping 需要它。

有关更多详细信息,请参见此处的交互式示例: https://regexr.com/54bm1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM