public ObjectNode toJson(IndexDefinition index) {
    ObjectNode node = JsonNodeFactory.instance.objectNode();

    node.put("name", index.getName());
    node.put("generalState", index.getGeneralState().toString());
    node.put("batchBuildState", index.getBatchBuildState().toString());
    node.put("updateState", index.getUpdateState().toString());

    node.put("zkDataVersion", index.getZkDataVersion());

    if (index.getQueueSubscriptionId() != null)
      node.put("queueSubscriptionId", index.getQueueSubscriptionId());

    String configurationAsString;
    try {
      configurationAsString = Base64.encodeBytes(index.getConfiguration(), Base64.GZIP);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }

    node.put("configuration", configurationAsString);

    if (index.getShardingConfiguration() != null) {
      String shardingConfAsString;
      try {
        shardingConfAsString = Base64.encodeBytes(index.getShardingConfiguration(), Base64.GZIP);
      } catch (IOException e) {
        throw new RuntimeException(e);
      }

      node.put("shardingConfiguration", shardingConfAsString);
    }

    ArrayNode shardsNode = node.putArray("solrShards");
    for (Map.Entry<String, String> shard : index.getSolrShards().entrySet()) {
      ObjectNode shardNode = shardsNode.addObject();
      shardNode.put("name", shard.getKey());
      shardNode.put("address", shard.getValue());
    }

    if (index.getActiveBatchBuildInfo() != null) {
      ActiveBatchBuildInfo buildInfo = index.getActiveBatchBuildInfo();
      ObjectNode buildNode = node.putObject("activeBatchBuild");
      buildNode.put("jobId", buildInfo.getJobId());
      buildNode.put("submitTime", buildInfo.getSubmitTime());
      buildNode.put("trackingUrl", buildInfo.getTrackingUrl());
      buildNode.put(
          "batchIndexConfiguration", deserializeByteArray(buildInfo.getBatchIndexConfiguration()));
    }

    if (index.getLastBatchBuildInfo() != null) {
      BatchBuildInfo buildInfo = index.getLastBatchBuildInfo();
      ObjectNode buildNode = node.putObject("lastBatchBuild");
      buildNode.put("jobId", buildInfo.getJobId());
      buildNode.put("submitTime", buildInfo.getSubmitTime());
      buildNode.put("success", buildInfo.getSuccess());
      buildNode.put("jobState", buildInfo.getJobState());
      if (buildInfo.getTrackingUrl() != null)
        buildNode.put("trackingUrl", buildInfo.getTrackingUrl());
      ObjectNode countersNode = buildNode.putObject("counters");
      for (Map.Entry<String, Long> counter : buildInfo.getCounters().entrySet()) {
        countersNode.put(counter.getKey(), counter.getValue());
      }
      buildNode.put(
          "batchIndexConfiguration", deserializeByteArray(buildInfo.getBatchIndexConfiguration()));
    }
    if (index.getBatchIndexConfiguration() != null) {
      node.put(
          "batchIndexConfiguration", this.deserializeByteArray(index.getBatchIndexConfiguration()));
    }
    if (index.getDefaultBatchIndexConfiguration() != null) {
      node.put(
          "defaultBatchIndexConfiguration",
          this.deserializeByteArray(index.getDefaultBatchIndexConfiguration()));
    }

    return node;
  }