public RebalanceInfo(JsonObject obj) throws RestApiException {
    JsonElement e = obj.get("status");
    if (e == null || e.isJsonPrimitive() == false) {
      throw new RestApiException("Expected status string", obj);
    }
    String sStatus = e.getAsString();
    if (sStatus.equals("none")) {
      completed = true;

    } else if (sStatus.equals("running")) {
      for (Entry<String,JsonElement> ent : obj.entrySet()) {
        if (ent.getKey().equals("status")) {
          continue;
        }
        JsonObject progressObj;
        if (ent.getValue().isJsonObject() == false) {
          throw new RestApiException("Expected object", ent.getValue());
        }
        progressObj = ent.getValue().getAsJsonObject();
        JsonElement progressNum = progressObj.get("progress");
        if (progressNum.isJsonPrimitive() == false ||
                progressNum.getAsJsonPrimitive().isNumber() == false) {
          throw new RestApiException("Expected 'progress' to be number",
                  progressNum);
        }
        details.put(ent.getKey(), progressNum.getAsNumber().floatValue() * 100);
      }
    }
  }