public static void main(String... strings) throws TrendrrException {
    String json = "blah blah{ \"key\" : \"value\"}{ \"key1\" : \"valu\\\"e1}\"}";

    try {
      json = FileHelper.loadString("tweetparse.json");
    } catch (Exception e) {
      log.error("Caught", e);
    }

    JSONStreamReader reader = new JSONStreamReader(new StringReader(json));
    DynMap mp;
    while ((mp = reader.readNext()) != null) {
      System.out.println(mp.toJSONString());
    }
  }
/**
 * Provides a way to read streams of json dictionaries.
 *
 * <p>will start a dictionary on the first '{' and finish the dict on the corresponding '}'
 *
 * <p>It will ignore any characters between dicts, so any dilimiter can be used. each dict must be
 * valid, an exception will be thrown on the first parse error.
 *
 * @author Dustin Norlander
 * @created Nov 2, 2011
 */
public class JSONStreamReader {

  protected static Log log = LogFactory.getLog(JSONStreamReader.class);

  Reader reader;

  long maxBufferedChars =
      FileHelper.megsToBytes(4); // max size to write before we assume this is an invalid stream.

  public JSONStreamReader(InputStream stream) {
    this(new InputStreamReader(stream));
  }

  public JSONStreamReader(Reader reader) {
    this.reader = new BufferedReader(reader);
  }

  public static void main(String... strings) throws TrendrrException {
    String json = "blah blah{ \"key\" : \"value\"}{ \"key1\" : \"valu\\\"e1}\"}";

    try {
      json = FileHelper.loadString("tweetparse.json");
    } catch (Exception e) {
      log.error("Caught", e);
    }

    JSONStreamReader reader = new JSONStreamReader(new StringReader(json));
    DynMap mp;
    while ((mp = reader.readNext()) != null) {
      System.out.println(mp.toJSONString());
    }
  }

  /**
   * returns null on eof. throws exception or returns parsed object.
   *
   * @return
   * @throws java.io.IOException
   */
  public DynMap readNext() throws TrendrrException {
    StringBuilder json = new StringBuilder("{");
    try {
      long numRead = 0;
      int openBrackets = 1;
      boolean isQuote = false;
      boolean isEscape = false;

      // read until the first open bracket
      int current = this.reader.read();
      while (current != '{' && current != -1) {
        numRead++;
        if (numRead > this.maxBufferedChars) {
          throw new TrendrrParseException(
              "Read "
                  + this.maxBufferedChars
                  + " chars without a valid json dict.  Beginning with: "
                  + json.substring(0, 256));
        }
        current = this.reader.read();
      }

      do {
        current = this.reader.read();
        if (current == -1) {
          return null;
        }
        char c = (char) current;
        json.append(c);
        if (!isQuote) {
          if (c == '{') {
            openBrackets++;
          } else if (c == '}') {
            openBrackets--;
          }
        }
        if (c == '"' && !isEscape) {
          isQuote = !isQuote;
        }

        if (isQuote && !isEscape && c == '\\') {
          isEscape = true;
        } else {
          isEscape = false;
        }

        numRead++;
        if (numRead > this.maxBufferedChars) {
          throw new TrendrrParseException(
              "Read "
                  + this.maxBufferedChars
                  + " chars without a valid json dict.  Beginning with: "
                  + json.substring(0, 256));
        }
      } while (openBrackets != 0);

      DynMap dm = DynMapFactory.instanceFromJSON(json.toString());
      if (dm == null) {
        throw new TrendrrParseException("unable to parse json string");
      }
      return dm;
    } catch (IOException x) {
      throw new TrendrrIOException(x);
    }
  }
}