Op extractOp(JSONObject object, Op parent) throws Exception {
    String[] names = JSONObject.getNames(object);
    if (names.length != 1) {
      throw new Exception("Expect only one operator in " + object.toString());
    } else {
      String opName = names[0];
      JSONObject attrObj = (JSONObject) object.get(opName);
      Map<String, String> attrs = new TreeMap<>();
      List<Op> children = new ArrayList<>();
      Op op = new Op(opName, null, null, parent, children, attrs, attrObj, this, parser);

      if (JSONObject.getNames(attrObj) != null) {
        for (String attrName : JSONObject.getNames(attrObj)) {
          if (attrName.equals("children")) {
            Object childrenObj = attrObj.get(attrName);
            if (childrenObj instanceof JSONObject nObject) {
              if (nObject.length() != 0) {
                children.add(extractOp(nObject, op));
              }
            } else if (childrenObj instanceof JSONArray nArray) {
              if (nArray.length() != 0) {
                for (int index = 0; index < nArray.length(); index++) {
                  children.add(extractOp(nArray.getJSONObject(index), op));
                }
              }
            } else {
              throw new Exception("Unsupported operator " + this.name
                      + "'s children operator is neither a jsonobject nor a jsonarray");
            }
          } else {
            if (attrName.equals("OperatorId:")) {
              op.setOperatorId(attrObj.get(attrName).toString());
            } else if (attrName.equals("outputname:")) {
              op.outputVertexName = attrObj.get(attrName).toString();
            } else {
              if (!attrObj.get(attrName).toString().isEmpty()) {
                attrs.put(attrName, attrObj.get(attrName).toString());
              }
            }
          }
        }
      }
      if (parent == null) {
        this.inputOps.add(op);
      }
      if (children.isEmpty()) {
        this.outputOps.add(op);
      }
      return op;
    }
  }
@param object
@param parent
@return
@throws Exception
          assumption: each operator only has one parent but may have many
          children
common/src/java/org/apache/hadoop/hive/common/jsonexplain/Vertex.java