public List collectJSONNodes(IStructuredModel model, int start, int length) {
    List nodes = new ArrayList();

    IndexedRegion startNode = model.getIndexedRegion(start);
    IndexedRegion endNode = model.getIndexedRegion(start + length - 1);

    if (startNode == null || endNode == null) {
      return nodes;
    }

    if (model instanceof IJSONModel
        && startNode instanceof IJSONNode
        && endNode instanceof IJSONNode) {
      // JSON model
      IJSONNode ca = getCommonAncestor((IJSONNode) startNode, (IJSONNode) endNode);
      if (ca != null) {
        for (IJSONNode node = ca.getFirstChild();
            node != null && start + length < ((IndexedRegion) node).getStartOffset();
            node = node.getNextSibling()) {
          if (start < ((IndexedRegion) node).getEndOffset()) {
            nodes.add(node);
          }
        }
      }
    }
    return nodes;
  }
 private static boolean isSimpleValue(IJSONNode node) {
   if (node == null) {
     return false;
   }
   return node.getNodeType() == IJSONNode.VALUE_BOOLEAN_NODE
       || node.getNodeType() == IJSONNode.VALUE_NULL_NODE
       || node.getNodeType() == IJSONNode.VALUE_NUMBER_NODE
       || node.getNodeType() == IJSONNode.VALUE_STRING_NODE;
 }
  private IJSONNode getCommonAncestor(IJSONNode nodeA, IJSONNode nodeB) {
    if (nodeA == null || nodeB == null) {
      return null;
    }

    for (IJSONNode na = nodeA; na != null; na = na.getParentNode()) {
      for (IJSONNode ta = nodeB; ta != null; ta = ta.getParentNode()) {
        if (ta == na) {
          return ta;
        }
      }
    }

    return null; // not found
  }
 private static boolean isArray(IJSONNode node) {
   if (node == null) {
     return false;
   }
   int nodeType = node.getNodeType();
   return nodeType == IJSONNode.ARRAY_NODE;
 }
 private static boolean isObject(IJSONNode node) {
   if (node == null) {
     return false;
   }
   int nodeType = node.getNodeType();
   return nodeType == IJSONNode.OBJECT_NODE;
 }
  private static IJSONPair findByPath(IJSONNode node, String name) {
    if (node == null || node.getNodeType() != IJSONNode.OBJECT_NODE) {
      return null;
    }

    IJSONObject obj = (IJSONObject) node;
    for (int i = 0; i < obj.getLength(); i++) {
      try {
        IJSONNode n = (IJSONNode) obj.getClass().getMethod("item", int.class).invoke(obj, i);
        if (n.getNodeType() == IJSONNode.PAIR_NODE) {
          IJSONPair pair = (IJSONPair) n;
          if (name.equals(pair.getName())) {
            return pair;
          }
        }
      } catch (Exception e) {
        return null;
      }
    }
    return null;
  }
  private static int getEndOffset(IJSONNode parent, boolean inside) {
    if (parent == null) {
      return 0;
    }
    switch (parent.getNodeType()) {
      case IJSONNode.OBJECT_NODE:
        if (parent.hasChildNodes()) {
          IJSONNode lastChild = parent.getLastChild();
          boolean childInside =
              inside
                  && (isSimpleValue(lastChild)
                      || (lastChild.getNodeType() == IJSONNode.PAIR_NODE
                          && isSimpleValue(((IJSONPair) lastChild).getValue())));
          return getEndOffset(lastChild, childInside);
        }
        return parent.getStartOffset() + (inside ? 1 : 0);
      case IJSONNode.PAIR_NODE:
        if (!inside) {
          return parent.getEndOffset();
        }

        IJSONPair pair = (IJSONPair) parent;
        IJSONValue value = (IJSONValue) pair.getValue();
        if (value != null) {
          return getEndOffset(value, false);
        }
        return pair.getEndOffset();
      case IJSONNode.VALUE_BOOLEAN_NODE:
      case IJSONNode.VALUE_NULL_NODE:
      case IJSONNode.VALUE_NUMBER_NODE:
      case IJSONNode.VALUE_STRING_NODE:
        return parent.getStartOffset()
            + parent.getFirstStructuredDocumentRegion().getFirstRegion().getLength();
      default:
        return parent.getEndOffset();
    }
  }
  public static void setValue(IStructuredDocument document, IJSONPath path, Object value) {
    IJSONModel model = null;
    try {
      model = (IJSONModel) StructuredModelManager.getModelManager().getModelForEdit(document);
      IJSONNode parent = model.getDocument().getFirstChild();
      String[] segments = path.getSegments();
      String name = null;
      int replaceOffset = 0;
      int replaceLength = 0;
      boolean isArray = false;
      int startIndex = NO_START_INDEX;
      StringBuilder newContent = new StringBuilder();
      for (int i = 0; i < segments.length; i++) {
        name = segments[i];
        isArray = isArray(path, i);
        IJSONPair node = findByPath(parent, name);
        if (node != null) {
          parent = node;
          IJSONNode jsonValue = node.getValue();
          if (isObject(jsonValue)) {
            parent = jsonValue;
            replaceOffset = getEndOffset(parent, true);
          } else {
            if (jsonValue != null) {
              replaceOffset = jsonValue.getStartOffset();
              replaceLength =
                  isArray(jsonValue)
                      ? jsonValue.getEndStructuredDocumentRegion().getEndOffset()
                          - jsonValue.getFirstStructuredDocumentRegion().getStartOffset()
                      : jsonValue.getFirstStructuredDocumentRegion().getFirstRegion().getLength();
            }
          }
        } else {
          if (isObjectOrArray(parent)) {
            replaceOffset = getEndOffset(parent, true);
            if (parent.hasChildNodes()) {
              newContent.append(",");
            }
          } else {
            newContent.append(isArray ? "[" : "{");
            if (startIndex == NO_START_INDEX) {
              startIndex = i - 1;
            }
          }
          newLineAndIndent(i, newContent);
          newContent.append("\"");
          newContent.append(name);
          newContent.append("\": ");
          parent = null;
        }
      }

      addValue(value, newContent);

      if (startIndex != NO_START_INDEX) {
        // close JSON object or Array
        for (int i = segments.length - 1; i > startIndex; i--) {
          if (i == -1) {
            newLineAndIndent(0, newContent);
            newContent.append("}");
          } else {
            name = segments[i];
            isArray = isArray(path, i);
            newLineAndIndent(i - 1, newContent);
            newContent.append(isArray ? "]" : "}");
          }
        }
      }
      document.replaceText(document, replaceOffset, replaceLength, newContent.toString());
    } finally {
      if (model != null) {
        model.releaseFromEdit();
      }
    }
  }