Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package divconq.json3;
  
Implementation of JSON Pointer specification. Pointer instances can be used to locate logical JSON nodes for things like tree traversal (see TreeNode). It may be used in future for filtering of streaming JSON content as well (not implemented yet for 2.3).

Instances are fully immutable and can be shared, cached.

Author(s):
Tatu Saloranta
Since:
2.3
 
 public class JsonPointer
 {
    
Marker instance used to represent segment that matches current node or position.
 
     protected final static JsonPointer EMPTY = new JsonPointer();
    
    
Reference to rest of the pointer beyond currently matching segment (if any); null if this pointer refers to a matching segment.
 
     protected final JsonPointer _nextSegment;
    
    
We will retain representation of the pointer, as a String, so that toString() should be as efficient as possible.
 
     protected final String _asString;
     
     protected final String _matchingPropertyName;
 
     protected final int _matchingElementIndex;
 
     /*
     /**********************************************************
     /* Cosntruction
     /**********************************************************
      */
     
     /*
      * Constructor used for creating "empty" instance, used to represent
      * state that matches current node.
      */
     protected JsonPointer() {
          = null;
          = "";
          = -1;
          = "";
     }
 
     /*
      * Constructor used for creating non-empty Segments
      */
     protected JsonPointer(String fullStringString segmentJsonPointer next) {
          = fullString;
          = next;
         // Ok; may always be a property
          = segment;
          = _parseIndex(segment);
     }
     
     /*
     /**********************************************************
     /* Factory methods
     /**********************************************************
      */
     
     /*
      * Factory method that parses given input and construct matching pointer
      * instance, if it represents a valid JSON Pointer: if not, a
      * {@link IllegalArgumentException} is thrown.
      * 
      * @throws IllegalArgumentException Thrown if the input does not present a valid JSON Pointer
      *   expression: currently the only such expression is one that does NOT start with
      *   a slash ('/').
      */
     public static JsonPointer compile(String inputthrows IllegalArgumentException
     {
         // First quick checks for well-known 'empty' pointer
         if ((input == null) || input.length() == 0) {
             return ;
         }
         // And then quick validity check:
         if (input.charAt(0) != '/') {
             throw new IllegalArgumentException("Invalid input: JSON Pointer expression must start with '/': "+"\""+input+"\"");
         }
         return _parseTail(input);
     }
    /*
     * Alias for {@link #compile}; added to make instances automatically
     * deserializable by Jackson databind.
     */
    public static JsonPointer valueOf(String input) { return compile(input); }
    /* Factory method that composes a pointer instance, given a set
     * of 'raw' segments: raw meaning that no processing will be done,
     * no escaping may is present.
     * 
     * @param segments
     * 
     * @return Constructed path instance
     */
    /* TODO!
    public static JsonPointer fromSegment(String... segments)
    {
        if (segments.length == 0) {
            return EMPTY;
        }
        JsonPointer prev = null;
                
        for (String segment : segments) {
            JsonPointer next = new JsonPointer()
        }
    }
    */
    
    /*
    /**********************************************************
    /* Public API
    /**********************************************************
     */
    public boolean matches() { return  == null; }
    public String getMatchingProperty() { return ; }
    public int getMatchingIndex() { return ; }
    public boolean mayMatchProperty() { return  != null; }
    public boolean mayMatchElement() { return  >= 0; }
    public JsonPointer matchProperty(String name) {
        if ( == null || !.equals(name)) {
            return null;
        }
        return ;
    }
    public JsonPointer matchElement (int index) {
        if ((index != ) || (index < 0)) {
            return null;
        }
        return ;
    }
    /*
     * Accessor for getting a "sub-pointer", instance where current segment
     * has been removed and pointer includes rest of segments;
     */
    public JsonPointer tail() {
        return ;
    }
    
    /*
    /**********************************************************
    /* Standard method overrides
    /**********************************************************
     */
    @Override public String toString() { return ; }
    @Override public int hashCode() { return .hashCode(); }
    @Override public boolean equals(Object o) {
        if (o == thisreturn true;
        if (o == nullreturn false;
        if (!(o instanceof JsonPointer)) return false;
        return .equals(((JsonPointero).);
    }
    
    /*
    /**********************************************************
    /* Internal methods
    /**********************************************************
     */
    private final static int _parseIndex(String str) {
        final int len = str.length();
        // [Issue#133]: beware of super long indexes; assume we never
        // have arrays over 2 billion entries so ints are fine.
        if (len == 0 || len > 10) {
            return -1;
        }
        for (int i = 0; i < len; ++i) {
            char c = str.charAt(i++);
            if (c > '9' || c < '0') {
                return -1;
            }
        }
        if (len == 10) {
            long l = NumberInput.parseLong(str);
            if (l > .) {
                return -1;
            }
        }
        return NumberInput.parseInt(str);
    }
    
    protected static JsonPointer _parseTail(String input) {
        final int end = input.length();
        // first char is the contextual slash, skip
        for (int i = 1; i < end; ) {
            char c = input.charAt(i);
            if (c == '/') { // common case, got a segment
                return new JsonPointer(inputinput.substring(1, i),
                        _parseTail(input.substring(i)));
            }
            ++i;
            // quoting is different; offline this case
            if (c == '~' && i < end) { // possibly, quote
                return _parseQuotedTail(inputi);
            }
            // otherwise, loop on
        }
        // end of the road, no escapes
        return new JsonPointer(inputinput.substring(1), );
    }
    /*
     * Method called to parse tail of pointer path, when a potentially
     * escaped character has been seen.
     * 
     * @param input Full input for the tail being parsed
     * @param i Offset to character after tilde
     */
    protected static JsonPointer _parseQuotedTail(String inputint i) {
        final int end = input.length();
        StringBuilder sb = new StringBuilder(Math.max(16, end));
        if (i > 2) {
            sb.append(input, 1, i-1);
        }
        _appendEscape(sbinput.charAt(i++));
        while (i < end) {
            char c = input.charAt(i);
            if (c == '/') { // end is nigh!
                return new JsonPointer(inputsb.toString(),
                        _parseTail(input.substring(i))); // need to push back slash
            }
            ++i;
            if (c == '~' && i < end) {
                _appendEscape(sbinput.charAt(i++));
                continue;
            }
            sb.append(c);
        }
        // end of the road, last segment
        return new JsonPointer(inputsb.toString(), );
    }
    
    private static void _appendEscape(StringBuilder sbchar c) {
        if (c == '0') {
            c = '~';
        } else if (c == '1') {
            c = '/';
        } else {
            sb.append('~');
        }
        sb.append(c);
    }
New to GrepCode? Check out our FAQ X