-
Notifications
You must be signed in to change notification settings - Fork 5
/
json.rb
113 lines (94 loc) · 3.13 KB
/
json.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
require 'multi_json'
require 'halibut/core'
module Halibut::Adapter
# This adapter converts Halibut::HAL::Resources to JSON encoded strings and back.
#
# resource = Halibut::Builder.new('http://example.com') do
# link "posts", '/posts'
# link "author", 'http://locks.io'
#
# property "title", 'Entry point'
# end.resource
#
# dumped = Halibut::Adapter::JSON.dump resource
# # => "{\"title\":\"Entry point\",\"_links\":{\"self\":{\"href\":\"http://example.com\"},\"posts\":{\"href\":\"/posts\"},\"author\":{\"href\":\"http://locks.io\"}}}"
#
# loaded = Halibut::Adapter::JSON.load dumped
# resource == loaded
# # => true
#
module JSON
def self.parse(json)
ResourceExtractor.new(json).resource
end
def self.render(resource)
MultiJson.dump resource.to_hash
end
private
# @deprecated Please use Halibut::Adapter::JSON.dump instead.
def self.extended(base)
base.extend InstanceMethods
end
module InstanceMethods
# @deprecated This might go.
def to_json
warn "[Deprecation] Don't depend on this, as it might disappear soon."
MultiJson.dump self.to_hash
end
end
# ResourceExtractor is responsible for deserializing an HAL resource
# from the JSON representation.
#
# extractor = ResourceExtractor.new({})
# # => #<Halibut::Adapter::JSON::ResourceExtractor:0x007f8adb92f2a8
# extractor.resource
# # => #<Halibut::HAL::Resource:0x007f8add058fb0
#
class ResourceExtractor
# Straight-forward, just pass in the JSON string you want to extract the
# resource from.
#
# json = '{"_links":{"self":{"href":"http://example.com"}}}'
# ResourceExtractor.new('{}')
#
def initialize(json)
@halibut = Halibut::Core::Resource.new
@json = MultiJson.load(json)
extract_properties
extract_links
extract_embedded_resources
end
# This method should be called when the the resource extracted is needed
def resource
@halibut
end
private
def extract_properties
properties = @json.reject {|k,v| k == '_links' }
.reject {|k,v| k == '_embedded' }
properties.each_pair do |property, value|
@halibut[property] = value
end
end
def extract_links
links = @json.fetch('_links', [])
links.each do |relation,values|
link = ([] << values).flatten
link.each do |attrs|
href = attrs.delete 'href'
@halibut.add_link(relation, Halibut::Core::Link.new(href, attrs))
end
end
end
def extract_embedded_resources
resources = @json.fetch('_embedded', [])
resources.each do |relation,values|
embeds = ([] << values).flatten
embeds.map {|embed| MultiJson.dump embed }
.map {|embed| Halibut::Adapter::JSON.parse embed }
.each {|embed| @halibut.embed_resource(relation, embed) }
end
end
end
end
end