All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.datastax.driver.core.SimpleJSONParser Maven / Gradle / Ivy

/*
 * Copyright DataStax, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.datastax.driver.core;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * A very simple json parser. The only reason we need to read json in the driver is because for
 * historical reason Cassandra encodes a few properties using json in the schema and we need to
 * decode them.
 *
 * 

We however don't need a full-blown JSON library because: 1) we know we only need to decode * string lists and string maps 2) we can basically assume the input is valid, we don't particularly * have to bother about decoding exactly JSON as long as we at least decode what we need. 3) we * don't really care much about performance, none of this is done in performance sensitive parts. * *

So instead of pulling a new dependency, we roll out our own very dumb parser. We should * obviously not expose this publicly. */ class SimpleJSONParser { private final String input; private int idx; private SimpleJSONParser(String input) { this.input = input; } public static List parseStringList(String input) { if (input == null || input.isEmpty()) return Collections.emptyList(); List output = new ArrayList(); SimpleJSONParser parser = new SimpleJSONParser(input); if (parser.nextCharSkipSpaces() != '[') throw new IllegalArgumentException("Not a JSON list: " + input); char c = parser.nextCharSkipSpaces(); if (c == ']') return output; while (true) { assert c == '"'; output.add(parser.nextString()); c = parser.nextCharSkipSpaces(); if (c == ']') return output; assert c == ','; c = parser.nextCharSkipSpaces(); } } public static Map parseStringMap(String input) { if (input == null || input.isEmpty()) return Collections.emptyMap(); Map output = new HashMap(); SimpleJSONParser parser = new SimpleJSONParser(input); if (parser.nextCharSkipSpaces() != '{') throw new IllegalArgumentException("Not a JSON map: " + input); char c = parser.nextCharSkipSpaces(); if (c == '}') return output; while (true) { assert c == '"'; String key = parser.nextString(); c = parser.nextCharSkipSpaces(); assert c == ':'; c = parser.nextCharSkipSpaces(); assert c == '"'; String value = parser.nextString(); output.put(key, value); c = parser.nextCharSkipSpaces(); if (c == '}') return output; assert c == ','; c = parser.nextCharSkipSpaces(); } } /** Read the next char, the one at position idx, and advance ix. */ private char nextChar() { if (idx >= input.length()) throw new IllegalArgumentException("Invalid json input: " + input); return input.charAt(idx++); } /** Same as nextChar, except that it skips space characters (' ', '\t' and '\n'). */ private char nextCharSkipSpaces() { char c = nextChar(); while (c == ' ' || c == '\t' || c == '\n') c = nextChar(); return c; } /** * Reads a String, assuming idx is on the first character of the string (i.e. the one after the * opening double-quote character). After the string has been read, idx will be on the first * character after the closing double-quote. */ private String nextString() { assert input.charAt(idx - 1) == '"' : "Char is '" + input.charAt(idx - 1) + '\''; StringBuilder sb = new StringBuilder(); while (true) { char c = nextChar(); switch (c) { case '\n': case '\r': throw new IllegalArgumentException("Unterminated string"); case '\\': c = nextChar(); switch (c) { case 'b': sb.append('\b'); break; case 't': sb.append('\t'); break; case 'n': sb.append('\n'); break; case 'f': sb.append('\f'); break; case 'r': sb.append('\r'); break; case 'u': sb.append((char) Integer.parseInt(input.substring(idx, idx + 4), 16)); idx += 4; break; case '"': case '\'': case '\\': case '/': sb.append(c); break; default: throw new IllegalArgumentException("Illegal escape"); } break; default: if (c == '"') return sb.toString(); sb.append(c); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy