Skip to content

Instantly share code, notes, and snippets.

@yuki24
Last active January 30, 2018 19:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yuki24/a3ec454963c1a1fc176d234e24564791 to your computer and use it in GitHub Desktop.
Save yuki24/a3ec454963c1a1fc176d234e24564791 to your computer and use it in GitHub Desktop.
better JSON serializer that returns an object with pre-defined attribute readers
require 'json'
require 'securerandom'
require 'delegate'
class ObjectMapper < SimpleDelegator
def self.parse(json_string, **opts)
JSON.parse(json_string, object_class: JsonHash, create_additions: true, create_id: JSON_CREADE_ID, **opts)
end
JSON_CREADE_ID = SecureRandom.uuid.freeze
alias parser __getobj__
def new(source, opts = {})
parser.new(source, object_class: JsonHash, create_additions: true, create_id: JSON_CREADE_ID, **opts)
end
class JsonHash < Hash
def [](key)
key == JSON_CREADE_ID ? JsonStruct : super
end
end
class JsonStruct
STRUCT_CACHE = Hash.new do |hash, key|
hash[key] = Struct.new(*key, keyword_init: true)
end
def self.json_creatable?
true
end
def self.json_create(result)
symbolized_result = result.transform_keys(&:to_sym)
STRUCT_CACHE[symbolized_result.keys].new(symbolized_result).freeze
end
end
private_constant :JsonHash, :JsonStruct
end
# Replace the default JSON parser:
JSON.parser = ObjectMapper.new(JSON.parser)
parsed = JSON.parse(<<-JSON)
{
"obj": {
"nested": 1
}
}
JSON
if parsed.obj.nested == 1
puts "success!"
else
raise "failed!"
end
# or call the ObjectMapper.parse method directly:
parsed = ObjectMapper.parse(<<-JSON)
{
"obj": {
"nested": 1
}
}
JSON
if parsed.obj.nested == 1
puts "success!"
else
raise "failed!"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment