用Java轻松解析JSON
我们有一个很大的JSON文件,其中NV对中的一些值有额外的用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": &
“
字符,这导致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"
}