private static View readView(JsonObject json, TextAnnotation ta) throws Exception {

    String viewClass = readString("viewType", json);

    String viewName = readString("viewName", json);

    String viewGenerator = readString("generator", json);

    double score = 0;
    if (json.has("score")) score = readDouble("score", json);

    View view = createEmptyView(ta, viewClass, viewName, viewGenerator, score);

    List<Constituent> constituents = new ArrayList<>();

    if (json.has("constituents")) {

      JsonArray cJson = json.getAsJsonArray("constituents");

      for (int i = 0; i < cJson.size(); i++) {
        JsonObject cJ = (JsonObject) cJson.get(i);
        Constituent c = readConstituent(cJ, ta, viewName);
        constituents.add(c);
        view.addConstituent(c);
      }
    }

    if (json.has("relations")) {
      JsonArray rJson = json.getAsJsonArray("relations");
      for (int i = 0; i < rJson.size(); i++) {
        JsonObject rJ = (JsonObject) rJson.get(i);

        String name = readString("relationName", rJ);

        double s = 0;
        if (rJ.has("score")) s = readDouble("score", rJ);

        int src = readInt("srcConstituent", rJ);
        int tgt = readInt("targetConstituent", rJ);

        Map<String, Double> labelsToScores = null;
        if (rJ.has(LABEL_SCORE_MAP)) {
          labelsToScores = new HashMap<>();
          readLabelsToScores(labelsToScores, rJ);
        }

        Relation rel = null;

        if (null == labelsToScores)
          rel = new Relation(name, constituents.get(src), constituents.get(tgt), s);
        else rel = new Relation(labelsToScores, constituents.get(src), constituents.get(tgt));

        readAttributes(rel, rJ);

        view.addRelation(rel);
      }
    }
    return view;
  }
  private static void writeView(View view, JsonObject json) {
    writeString("viewType", view.getClass().getCanonicalName(), json);

    writeString("viewName", view.getViewName(), json);

    writeString("generator", view.getViewGenerator(), json);

    if (view.getScore() != 0) writeDouble("score", view.getScore(), json);

    List<Constituent> constituents = view.getConstituents();

    if (constituents.size() > 0) {
      JsonArray cJson = new JsonArray();
      for (int i = 0; i < view.getNumberOfConstituents(); i++) {

        Constituent constituent = constituents.get(i);
        JsonObject c = new JsonObject();
        writeConstituent(constituent, c);

        cJson.add(c);
      }

      json.add("constituents", cJson);
    }

    List<Relation> relations = view.getRelations();

    if (relations.size() > 0) {

      JsonArray rJson = new JsonArray();

      for (Relation r : relations) {
        Constituent src = r.getSource();
        Constituent tgt = r.getTarget();

        int srcId = constituents.indexOf(src);
        int tgtId = constituents.indexOf(tgt);

        JsonObject rJ = new JsonObject();

        writeString("relationName", r.getRelationName(), rJ);

        if (r.getScore() != 0) writeDouble("score", r.getScore(), rJ);
        writeInt("srcConstituent", srcId, rJ);
        writeInt("targetConstituent", tgtId, rJ);
        writeAttributes(r, rJ);

        Map<String, Double> labelsToScores = r.getLabelsToScores();

        if (null != labelsToScores) writeLabelsToScores(labelsToScores, rJ);

        rJson.add(rJ);
      }

      json.add("relations", rJson);
    }
  }
  TextAnnotation readTextAnnotation(String string) throws Exception {
    JsonObject json = (JsonObject) new JsonParser().parse(string);

    String corpusId = readString("corpusId", json);
    String id = readString("id", json);
    String text = readString("text", json);
    String[] tokens = readStringArray("tokens", json);

    Pair<Pair<String, Double>, int[]> sentences = readSentences(json);

    IntPair[] offsets = TokenUtils.getTokenOffsets(text, tokens);

    TextAnnotation ta =
        new TextAnnotation(corpusId, id, text, offsets, tokens, sentences.getSecond());

    JsonArray views = json.getAsJsonArray("views");
    for (int i = 0; i < views.size(); i++) {
      JsonObject view = (JsonObject) views.get(i);
      String viewName = readString("viewName", view);

      JsonArray viewData = view.getAsJsonArray("viewData");
      List<View> topKViews = new ArrayList<>();

      for (int k = 0; k < viewData.size(); k++) {
        JsonObject kView = (JsonObject) viewData.get(k);

        topKViews.add(readView(kView, ta));
      }

      ta.addTopKView(viewName, topKViews);
    }

    readAttributes(ta, json);

    return ta;
  }