Skip to content

Instantly share code, notes, and snippets.

@Bonemind
Last active April 26, 2018 20:29
Show Gist options
  • Select an option

  • Save Bonemind/c67ba23f98f47a82bb59eb7e0630233b to your computer and use it in GitHub Desktop.

Select an option

Save Bonemind/c67ba23f98f47a82bb59eb7e0630233b to your computer and use it in GitHub Desktop.
require "json"
class Test
exclude_names = ["to_json"]
def initialize
@testv = 10
@testvb = 10
end
def testf()
puts "testf"
return @testv
end
def vs
return {a: "b", c: "d"}
end
macro jsonifier(exclude_names = [] of String, include_names = [] of String, include_methods = [] of String)
def to_json
String.build do |str|
to_json str
end
end
def to_json(io : IO)
{% begin %}
JSON.build(io) do |json|
json.object do
# all instance vars
to_serialize = \{{ @type.instance_vars.map &.id.stringify }}
# remove any exclusions
to_serialize = to_serialize - {{ exclude_names }}
# remove anything that isn't explicitly included
# unless inclusions is blank, then we include all
include_names = {{ include_names }}
to_serialize.reject! do |n|
!include_names.includes?(n)
end unless include_names.empty?
# generate a json.field entry for every ivar, but only serialize if included
# Works this way because we don't have access to both ivars and the macro vars at the same time
# so we determine serializiation at runtime based on an if
\{% for ivar in @type.instance_vars %}
json.field \{{ ivar.id.stringify }}, @\{{ ivar.id }} if to_serialize.includes?(\{{ivar.id.stringify}})
\{% end %}
# also add any methods that are included
{% for klass in @type.methods %}
{% if include_methods.includes?(klass.name.stringify) %}
json.field {{ klass.name.stringify }}, {{ klass.name }}
{% end %}
{% end %}
end
end
{% end %}
end
end
jsonifier(exclude_names: ["testv"] of String, include_methods: ["vs"])
end
t = Test.new
puts t.vs
puts t.to_json
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment