Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用Java轻松解析JSON_Java_Json - Fatal编程技术网

用Java轻松解析JSON

用Java轻松解析JSON,java,json,Java,Json,我们有一个很大的JSON文件,其中NV对中的一些值有额外的“字符,这导致Java解析失败 { "sample-data": [ { "name": "Peter Smith", "comment": "A quick brown fox jumps over the lazy dog" }, { "name": &

我们有一个很大的JSON文件,其中NV对中的一些值有额外的
字符,这导致Java解析失败

{
  "sample-data": [
    {
      "name": "Peter Smith",
      "comment": "A quick brown fox jumps over the lazy dog"
    },
    {
      "name": "John Doe",
      "comment": "This is so cool"
    },
    {
      "name": "Amy Brown",
      "comment": "He just exclaimed "OMG" when I approached him"
    },
    {
      "name": "Ronnie Arbuckle",
      "comment": "Peter O"Toole is a great bloke"
    }
  ]
}
这里是JSON对象

{
  "name": "Amy Brown",
  "comment": "He just exclaimed "OMG" when I approached him"
}

是那些有额外
问题的


Q):有没有一种方法可以用Java执行“轻松的JSON解析”
我们可以在这个过程中丢失一些对象的数据,但我们希望尽可能多地保留数据。

如果您需要稍微修改原始文件的内容,我建议编写一个实现java.io.Reader/java.io.InputStream的自定义包装器,并将这个Reader/stream传递给您的解析库。此包装器动态修改内容。例如:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;

public class JsonFixer {
    private static final String CORRUPTED_JSON = "{\n" +
            "  \"name\": \"Amy Brown\",\n" +
            "  \"value\": 123,\n" +
            "  \"comment\": \"He just exclaimed \"OMG\" when I approached him\",\n" +
            "  \"comment\": \"He just exclaimed \\\"OMG\" when I approached him\",\n" +
            "  \"comment\": \"He just exclaimed \\\"OMG\\\" when I approached him\"\n" +
            "}";

    public static class FixingReader extends Reader {
        private final StringBuilder fixedLine = new StringBuilder();

        private final BufferedReader lineReader;

        private char[] currentLine;
        private int currentLineStart;
        private int currentLineLength;

        public FixingReader(final Reader reader) {
            if (reader instanceof BufferedReader) {
                lineReader = (BufferedReader) reader;
            } else {
                lineReader = new BufferedReader(reader);
            }
        }

        @Override
        public int read(final char[] cbuf, final int off, final int len) throws IOException {
            if (currentLineLength > 0) { // make the read of the rest of line
                final int left = currentLineLength - currentLineStart;
                final int read = Math.min(len, left);
                System.arraycopy(currentLine, currentLineStart, cbuf, off, read);
                currentLineStart += read;
                if (currentLineStart == currentLineLength) {
                    currentLineStart = 0;
                    currentLineLength = 0;
                }
                return read;
            }

            final String line = lineReader.readLine();
            if (line == null) { // EOF
                currentLineStart = 0;
                currentLineLength = 0;
                return -1;
            }

            int lineLength = line.length() + 1; // including \n on the end of the line to be restored
            currentLine = currentLine == null || currentLine.length < lineLength ?
                    new char[lineLength] :
                    currentLine; // reuse if we have enough space
            line.getChars(0, line.length(), currentLine, 0);
            currentLine[lineLength - 1] = '\n';
            fixedLine.setLength(0);

            // find the opening quotation mark
            int openQuoteIdx = -1;
            int qtCnt = 0;
            for (int i = 0; i < lineLength; i++) {
                final char c = currentLine[i];
                fixedLine.append(c); // write start of the line
                if (c != '"') {
                    continue;
                }
                qtCnt++;
                if (qtCnt == 3) {
                    openQuoteIdx = i;
                    break;
                }
            }
            // find the closing quotation mark
            int closeQuoteIdx = -1;
            for (int i = lineLength - 1; i > 0; i--) {
                if (currentLine[i] != '"') {
                    continue;
                }
                closeQuoteIdx = i;
                break;
            }
            if (openQuoteIdx > -1) { // if the line has quotation marks for the value
                // copy the rest of the string replacing the quotation mark
                boolean wasQuoted = false;
                for (int i = openQuoteIdx + 1; i < lineLength; i++) {
                    final char c = currentLine[i];
                    if (i >= closeQuoteIdx) {
                        fixedLine.append(c); // write end of the line
                        continue;
                    }
                    // can see a quotation mark
                    switch (c) {
                        case '\\':
                            wasQuoted = true;
                            break;
                        case '"':
                            if (!wasQuoted) {
                                fixedLine.append('\\');
                            }
                        default:
                            wasQuoted = false;
                    }
                    fixedLine.append(c);
                }
                if (fixedLine.length() > lineLength) {
                    currentLine = new char[fixedLine.length()];
                    fixedLine.getChars(0, fixedLine.length(), currentLine, 0);
                    lineLength = currentLine.length;
                }
            }

            currentLineStart = 0;
            currentLineLength = lineLength;

            // make the read
            final int read = Math.min(len, currentLineLength);
            System.arraycopy(currentLine, currentLineStart, cbuf, off, read);
            currentLineStart += read;
            if (currentLineStart == currentLineLength) {
                currentLineLength = 0;
            }
            return read;
        }

        @Override
        public void close() throws IOException {
            lineReader.close();
        }
    }

    public static void main(String[] args) throws Exception {
        try (BufferedReader fixedJson = new BufferedReader(new FixingReader(new StringReader(CORRUPTED_JSON)))) {
            fixedJson.lines().forEach(System.out::println);
        }
    }
}

这种轻量级方法允许您甚至转换大型文件,因为它一次只需要存储一行。此特定实现仅适用于一行包含不超过一个对象属性及其值的情况。否则,您必须正确修改解析。

您不能在注释中转义引号吗?“彼得·奥”图尔是个了不起的家伙"? 并使JSON格式良好且可解析?@Heiko Jakubzik JSON文件已传递给我们。我们不是从头开始创建的。告诉将JSON文件交给您的人修复他们的错误代码。文件的格式是否如图所示?因为这样你就可以在每一行中转义除第一、第二、第三和最后一个外的每一个双引号…@Siguza这只是我创建的一个示例文件来说明这个问题。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;

public class JsonFixer {
    private static final String CORRUPTED_JSON = "{\n" +
            "  \"name\": \"Amy Brown\",\n" +
            "  \"value\": 123,\n" +
            "  \"comment\": \"He just exclaimed \"OMG\" when I approached him\",\n" +
            "  \"comment\": \"He just exclaimed \\\"OMG\" when I approached him\",\n" +
            "  \"comment\": \"He just exclaimed \\\"OMG\\\" when I approached him\"\n" +
            "}";

    public static class FixingReader extends Reader {
        private final StringBuilder fixedLine = new StringBuilder();

        private final BufferedReader lineReader;

        private char[] currentLine;
        private int currentLineStart;
        private int currentLineLength;

        public FixingReader(final Reader reader) {
            if (reader instanceof BufferedReader) {
                lineReader = (BufferedReader) reader;
            } else {
                lineReader = new BufferedReader(reader);
            }
        }

        @Override
        public int read(final char[] cbuf, final int off, final int len) throws IOException {
            if (currentLineLength > 0) { // make the read of the rest of line
                final int left = currentLineLength - currentLineStart;
                final int read = Math.min(len, left);
                System.arraycopy(currentLine, currentLineStart, cbuf, off, read);
                currentLineStart += read;
                if (currentLineStart == currentLineLength) {
                    currentLineStart = 0;
                    currentLineLength = 0;
                }
                return read;
            }

            final String line = lineReader.readLine();
            if (line == null) { // EOF
                currentLineStart = 0;
                currentLineLength = 0;
                return -1;
            }

            int lineLength = line.length() + 1; // including \n on the end of the line to be restored
            currentLine = currentLine == null || currentLine.length < lineLength ?
                    new char[lineLength] :
                    currentLine; // reuse if we have enough space
            line.getChars(0, line.length(), currentLine, 0);
            currentLine[lineLength - 1] = '\n';
            fixedLine.setLength(0);

            // find the opening quotation mark
            int openQuoteIdx = -1;
            int qtCnt = 0;
            for (int i = 0; i < lineLength; i++) {
                final char c = currentLine[i];
                fixedLine.append(c); // write start of the line
                if (c != '"') {
                    continue;
                }
                qtCnt++;
                if (qtCnt == 3) {
                    openQuoteIdx = i;
                    break;
                }
            }
            // find the closing quotation mark
            int closeQuoteIdx = -1;
            for (int i = lineLength - 1; i > 0; i--) {
                if (currentLine[i] != '"') {
                    continue;
                }
                closeQuoteIdx = i;
                break;
            }
            if (openQuoteIdx > -1) { // if the line has quotation marks for the value
                // copy the rest of the string replacing the quotation mark
                boolean wasQuoted = false;
                for (int i = openQuoteIdx + 1; i < lineLength; i++) {
                    final char c = currentLine[i];
                    if (i >= closeQuoteIdx) {
                        fixedLine.append(c); // write end of the line
                        continue;
                    }
                    // can see a quotation mark
                    switch (c) {
                        case '\\':
                            wasQuoted = true;
                            break;
                        case '"':
                            if (!wasQuoted) {
                                fixedLine.append('\\');
                            }
                        default:
                            wasQuoted = false;
                    }
                    fixedLine.append(c);
                }
                if (fixedLine.length() > lineLength) {
                    currentLine = new char[fixedLine.length()];
                    fixedLine.getChars(0, fixedLine.length(), currentLine, 0);
                    lineLength = currentLine.length;
                }
            }

            currentLineStart = 0;
            currentLineLength = lineLength;

            // make the read
            final int read = Math.min(len, currentLineLength);
            System.arraycopy(currentLine, currentLineStart, cbuf, off, read);
            currentLineStart += read;
            if (currentLineStart == currentLineLength) {
                currentLineLength = 0;
            }
            return read;
        }

        @Override
        public void close() throws IOException {
            lineReader.close();
        }
    }

    public static void main(String[] args) throws Exception {
        try (BufferedReader fixedJson = new BufferedReader(new FixingReader(new StringReader(CORRUPTED_JSON)))) {
            fixedJson.lines().forEach(System.out::println);
        }
    }
}
{
  "name": "Amy Brown",
  "value": 123,
  "comment": "He just exclaimed \"OMG\" when I approached him",
  "comment": "He just exclaimed \"OMG\" when I approached him",
  "comment": "He just exclaimed \"OMG\" when I approached him"
}