Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 0 additions & 26 deletions spec/std/json/any_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -86,24 +86,6 @@ describe JSON::Any do
end
end

describe "each" do
it "of array" do
elems = [] of Int32
JSON.parse("[1, 2, 3]").each do |any|
elems << any.as_i
end
elems.should eq([1, 2, 3])
end

it "of hash" do
elems = [] of String
JSON.parse(%({"foo": "bar"})).each do |key, value|
elems << key.to_s << value.to_s
end
elems.should eq(%w(foo bar))
end
end

it "traverses big structure" do
obj = JSON.parse(%({"foo": [1, {"bar": [2, 3]}]}))
obj["foo"][1]["bar"][1].as_i.should eq(3)
Expand All @@ -123,12 +105,4 @@ describe JSON::Any do
(/o+/ === JSON.parse(%("foo"))).should be_truthy
$~[0].should eq("oo")
end

it "is enumerable" do
nums = JSON.parse("[1, 2, 3]")
nums.each_with_index do |x, i|
x.should be_a(JSON::Any)
x.raw.should eq(i + 1)
end
end
end
4 changes: 2 additions & 2 deletions spec/std/json/parser_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe JSON::Parser do
it_parses "[0]", [0]
it_parses " [ 0 ] ", [0]

it_parses "{}", {} of String => JSON::Type
it_parses "{}", {} of String => JSON::Any
it_parses %({"foo": 1}), {"foo" => 1}
it_parses %({"foo": 1, "bar": 1.5}), {"foo" => 1, "bar" => 1.5}
it_parses %({"fo\\no": 1}), {"fo\no" => 1}
Expand Down Expand Up @@ -75,7 +75,7 @@ describe JSON::Parser do
end

it "returns raw" do
value = JSON.parse_raw("1")
value = JSON.parse("1").raw
value.should eq(1)
value.should be_a(Int64)
end
Expand Down
6 changes: 3 additions & 3 deletions spec/std/json/pull_parser_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,16 @@ class JSON::PullParser
def assert(array : Array)
assert_array do
array.each do |x|
assert x
assert x.raw
end
end
end

def assert(hash : Hash)
assert_object do
hash.each do |key, value|
assert(key.as(String)) do
assert value
assert(key) do
assert value.raw
end
end
end
Expand Down
20 changes: 1 addition & 19 deletions spec/std/yaml/any_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -128,24 +128,6 @@ describe YAML::Any do
end
end

describe "each" do
it "of array" do
elems = [] of String
YAML.parse("- foo\n- bar\n").each do |any|
elems << any.as_s
end
elems.should eq(%w(foo bar))
end

it "of hash" do
elems = [] of String
YAML.parse("foo: bar").each do |key, value|
elems << key.to_s << value.to_s
end
elems.should eq(%w(foo bar))
end
end

it "traverses big structure" do
obj = YAML.parse("--- \nfoo: \n bar: \n baz: \n - qux\n - fox")
obj["foo"]["bar"]["baz"][1].as_s.should eq("fox")
Expand Down Expand Up @@ -174,7 +156,7 @@ describe YAML::Any do

it "is enumerable" do
nums = YAML.parse("[1, 2, 3]")
nums.each_with_index do |x, i|
nums.as_a.each_with_index do |x, i|
x.should be_a(YAML::Any)
x.raw.should eq(i + 1)
end
Expand Down
4 changes: 2 additions & 2 deletions spec/std/yaml/schema/core_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ private def it_parses_scalar_from_pull(string, expected, file = __FILE__, line =
end
end

private def it_parses_scalar_from_pull(string, file = __FILE__, line = __LINE__, &block : YAML::Type ->)
private def it_parses_scalar_from_pull(string, file = __FILE__, line = __LINE__, &block : YAML::Any::Type ->)
it "parses #{string.inspect}", file, line do
pull = YAML::PullParser.new(%(value: #{string}))
pull.read_stream_start
pull.read_document_start
pull.read_mapping_start
pull.read_scalar # key

block.call(YAML::Schema::Core.parse_scalar(pull).as(YAML::Type))
block.call(YAML::Schema::Core.parse_scalar(pull).as(YAML::Any::Type))
end
end

Expand Down
8 changes: 4 additions & 4 deletions spec/std/yaml/yaml_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,26 @@ describe "YAML" do
it { YAML.parse("- foo\n- bar").should eq(["foo", "bar"]) }
it { YAML.parse_all("---\nfoo\n---\nbar\n").should eq(["foo", "bar"]) }
it { YAML.parse("foo: bar").should eq({"foo" => "bar"}) }
it { YAML.parse("--- []\n").should eq([] of YAML::Type) }
it { YAML.parse("--- []\n").should eq([] of YAML::Any) }
it { YAML.parse("---\n...").should eq nil }

it "parses recursive sequence" do
doc = YAML.parse("--- &foo\n- *foo\n")
doc[0].raw.as(Array).should be(doc.raw.as(Array))
doc[0].as_a.should be(doc.raw.as(Array))
end

it "parses recursive mapping" do
doc = YAML.parse(%(--- &1
friends:
- *1
))
doc["friends"][0].raw.as(Hash).should be(doc.raw.as(Hash))
doc["friends"][0].as_h.should be(doc.as_h)
end

it "parses alias to scalar" do
doc = YAML.parse("---\n- &x foo\n- *x\n")
doc.should eq(["foo", "foo"])
doc[0].raw.as(String).should be(doc[1].raw.as(String))
doc[0].as_s.should be(doc[1].as_s)
end

describe "merging with << key" do
Expand Down
8 changes: 0 additions & 8 deletions src/json.cr
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,8 @@ module JSON
end
end

# All valid JSON types.
alias Type = Nil | Bool | Int64 | Float64 | String | Array(Type) | Hash(String, Type)

# Parses a JSON document as a `JSON::Any`.
def self.parse(input : String | IO) : Any
Any.new parse_raw(input)
end

# Parses a JSON document as a `JSON::Type`.
def self.parse_raw(input : String | IO) : Type
Parser.new(input).parse
end
end
Expand Down
85 changes: 45 additions & 40 deletions src/json/any.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# `JSON::Any` is a convenient wrapper around all possible JSON types (`JSON::Type`)
# `JSON::Any` is a convenient wrapper around all possible JSON types (`JSON::Any::Type`)
# and can be used for traversing dynamic or unknown JSON structures.
#
# ```
Expand All @@ -14,7 +14,8 @@
# when the underlying value is not a String will raise: the value won't automatically
# be converted (parsed) to a `String`.
struct JSON::Any
include Enumerable(self)
# All possible JSON types.
alias Type = Nil | Bool | Int64 | Float64 | String | Array(Any) | Hash(String, Any)

# Reads a `JSON::Any` value from the given pull parser.
def self.new(pull : JSON::PullParser)
Expand All @@ -30,27 +31,27 @@ struct JSON::Any
when :string
new pull.read_string
when :begin_array
ary = [] of JSON::Type
ary = [] of JSON::Any
pull.read_array do
ary << new(pull).raw
ary << new(pull)
end
new ary
when :begin_object
hash = {} of String => JSON::Type
hash = {} of String => JSON::Any
pull.read_object do |key|
hash[key] = new(pull).raw
hash[key] = new(pull)
end
new hash
else
raise "Unknown pull kind: #{pull.kind}"
end
end

# Returns the raw underlying value, a `JSON::Type`.
getter raw : JSON::Type
# Returns the raw underlying value.
getter raw : Type

# Creates a `JSON::Any` that wraps the given `JSON::Type`.
def initialize(@raw : JSON::Type)
# Creates a `JSON::Any` that wraps the given value.
def initialize(@raw : Type)
end

# Assumes the underlying value is an `Array` or `Hash` and returns its size.
Expand All @@ -72,7 +73,7 @@ struct JSON::Any
def [](index : Int) : JSON::Any
case object = @raw
when Array
Any.new object[index]
object[index]
else
raise "Expected Array for #[](index : Int), not #{object.class}"
end
Expand All @@ -84,8 +85,7 @@ struct JSON::Any
def []?(index : Int) : JSON::Any?
case object = @raw
when Array
value = object[index]?
value.nil? ? nil : Any.new(value)
object[index]?
else
raise "Expected Array for #[]?(index : Int), not #{object.class}"
end
Expand All @@ -97,7 +97,7 @@ struct JSON::Any
def [](key : String) : JSON::Any
case object = @raw
when Hash
Any.new object[key]
object[key]
else
raise "Expected Hash for #[](key : String), not #{object.class}"
end
Expand All @@ -109,31 +109,12 @@ struct JSON::Any
def []?(key : String) : JSON::Any?
case object = @raw
when Hash
value = object[key]?
value.nil? ? nil : Any.new(value)
object[key]?
else
raise "Expected Hash for #[]?(key : String), not #{object.class}"
end
end

# Assumes the underlying value is an `Array` or `Hash` and yields each
# of the elements or key/values, always as `JSON::Any`.
# Raises if the underlying value is not an `Array` or `Hash`.
def each
case object = @raw
when Array
object.each do |elem|
yield Any.new(elem), Any.new(nil)
end
when Hash
object.each do |key, value|
yield Any.new(key), Any.new(value)
end
else
raise "Expected Array or Hash for #each, not #{object.class}"
end
end

# Checks that the underlying value is `Nil`, and returns `nil`.
# Raises otherwise.
def as_nil : Nil
Expand Down Expand Up @@ -214,26 +195,26 @@ struct JSON::Any

# Checks that the underlying value is `Array`, and returns its value.
# Raises otherwise.
def as_a : Array(Type)
def as_a : Array(Any)
@raw.as(Array)
end

# Checks that the underlying value is `Array`, and returns its value.
# Returns `nil` otherwise.
def as_a? : Array(Type)?
as_a if @raw.is_a?(Array(Type))
def as_a? : Array(Any)?
as_a if @raw.is_a?(Array)
end

# Checks that the underlying value is `Hash`, and returns its value.
# Raises otherwise.
def as_h : Hash(String, Type)
def as_h : Hash(String, Any)
@raw.as(Hash)
end

# Checks that the underlying value is `Hash`, and returns its value.
# Returns `nil` otherwise.
def as_h? : Hash(String, Type)?
as_h if @raw.is_a?(Hash(String, Type))
def as_h? : Hash(String, Any)?
as_h if @raw.is_a?(Hash)
end

# :nodoc:
Expand Down Expand Up @@ -276,6 +257,30 @@ class Object
end
end

struct Value
def ==(other : JSON::Any)
self == other.raw
end
end

class Reference
def ==(other : JSON::Any)
self == other.raw
end
end

class Array
def ==(other : JSON::Any)
self == other.raw
end
end

class Hash
def ==(other : JSON::Any)
self == other.raw
end
end

class Regex
def ===(other : JSON::Any)
value = self === other.raw
Expand Down
Loading