Class: JSON::Schema::Pointer

Inherits:
Object
  • Object
show all
Defined in:
lib/scorpio/json-schema-fragments.rb

Overview

a JSON Pointer, as described by RFC 6901 tools.ietf.org/html/rfc6901

Defined Under Namespace

Classes: Error, PointerSyntaxError, ReferenceError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(type, representation) ⇒ Pointer

initializes a JSON::Schema::Pointer from the given representation.

type may be one of:

  • :fragment - the representation is a fragment containing a pointer (starting with #)

  • :pointer - the representation is a pointer (starting with /)

  • :reference_tokens - the representation is an array of tokens referencing a path in a document



67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/scorpio/json-schema-fragments.rb', line 67

def initialize(type, representation)
  @type = type
  if type == :reference_tokens
    reference_tokens = representation
  elsif type == :fragment
    reference_tokens = self.class.parse_fragment(representation)
  elsif type == :pointer
    reference_tokens = self.class.parse_pointer(representation)
  else
    raise ArgumentError, "invalid initialization type: #{type.inspect} with representation #{representation.inspect}"
  end
  @reference_tokens = reference_tokens.map(&:freeze).freeze
end

Instance Attribute Details

#reference_tokensObject (readonly)

Returns the value of attribute reference_tokens.



81
82
83
# File 'lib/scorpio/json-schema-fragments.rb', line 81

def reference_tokens
  @reference_tokens
end

Class Method Details

.parse_fragment(fragment) ⇒ Object

parse a fragment to an array of reference tokens

#/foo/bar

> [‘foo’, ‘bar’]

#/foo%20bar

> [‘foo bar’]



28
29
30
31
32
33
34
35
36
# File 'lib/scorpio/json-schema-fragments.rb', line 28

def self.parse_fragment(fragment)
  fragment = Addressable::URI.unescape(fragment)
  match = fragment.match(/\A#/)
  if match
    parse_pointer(match.post_match)
  else
    raise(PointerSyntaxError, "Invalid fragment syntax in #{fragment.inspect}: fragment must begin with #")
  end
end

.parse_pointer(pointer_string) ⇒ Object

parse a pointer to an array of reference tokens

/foo

> [‘foo’]

/foo~0bar/baz~1qux

> [‘foo~bar’, ‘baz/qux’]



47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/scorpio/json-schema-fragments.rb', line 47

def self.parse_pointer(pointer_string)
  tokens = pointer_string.split('/', -1).map! do |piece|
    piece.gsub('~1', '/').gsub('~0', '~')
  end
  if tokens[0] == ''
    tokens[1..-1]
  elsif tokens.empty?
    tokens
  else
    raise(PointerSyntaxError, "Invalid pointer syntax in #{pointer_string.inspect}: pointer must begin with /")
  end
end

Instance Method Details

#evaluate(document) ⇒ Object

takes a root json document and evaluates this pointer through the document, returning the value pointed to by this pointer.



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/scorpio/json-schema-fragments.rb', line 85

def evaluate(document)
  reference_tokens.inject(document) do |value, token|
    if value.is_a?(Array)
      if token.is_a?(String) && token =~ /\A\d|[1-9]\d+\z/
        token = token.to_i
      end
      unless token.is_a?(Integer)
        raise(ReferenceError, "Invalid resolution for #{to_s}: #{token.inspect} is not an integer and cannot be resolved in array #{value.inspect}")
      end
      unless (0...value.size).include?(token)
        raise(ReferenceError, "Invalid resolution for #{to_s}: #{token.inspect} is not a valid index of #{value.inspect}")
      end
    elsif value.is_a?(Hash)
      unless value.key?(token)
        raise(ReferenceError, "Invalid resolution for #{to_s}: #{token.inspect} is not a valid key of #{value.inspect}")
      end
    else
      raise(ReferenceError, "Invalid resolution for #{to_s}: #{token.inspect} cannot be resolved in #{value.inspect}")
    end
    value[token]
  end
end

#fragmentObject

the fragment string representation of this Pointer



114
115
116
# File 'lib/scorpio/json-schema-fragments.rb', line 114

def fragment
  '#' + Addressable::URI.escape(pointer)
end

#pointerObject

the pointer string representation of this Pointer



109
110
111
# File 'lib/scorpio/json-schema-fragments.rb', line 109

def pointer
  reference_tokens.map { |t| '/' + t.to_s.gsub('~', '~0').gsub('/', '~1') }.join('')
end

#to_sObject



118
119
120
# File 'lib/scorpio/json-schema-fragments.rb', line 118

def to_s
  "#<#{self.class.inspect} #{@type} = #{representation_s}>"
end