json_serializers 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_model_serializers'
4
+
5
+ # Extensions: To ensure JsonStringEncoder can process ActiveModel::Serializer
6
+ # as well.
7
+ class ActiveModel::Serializer
8
+ # JsonStringEncoder: Used internally to write a single object to JSON.
9
+ def self.one(object, options = nil)
10
+ new(object, options)
11
+ end
12
+
13
+ # JsonStringEncoder: Used internally to write an array of objects to JSON.
14
+ def self.many(array, options = nil)
15
+ array.map { |object| new(object, options) }
16
+ end
17
+
18
+ # JsonSerializer: Used internally to write a single object association in :hash mode.
19
+ #
20
+ # Returns nothing.
21
+ def self.one_as_hash(object)
22
+ new(object)
23
+ end
24
+
25
+ # JsonSerializer: Used internally to write an association in :hash mode.
26
+ #
27
+ # Returns nothing.
28
+ def self.many_as_hash(array)
29
+ array.map { |object| new(object) }
30
+ end
31
+
32
+ # JsonSerializer: Used internally to write a single object association in :json mode.
33
+ #
34
+ # Returns nothing.
35
+ def self.write_one(writer, object)
36
+ writer.push_value(new(object))
37
+ end
38
+
39
+ # JsonSerializer: Used internally to write an association in :json mode.
40
+ #
41
+ # Returns nothing.
42
+ def self.write_many(writer, array)
43
+ writer.push_array
44
+ array.each do |object|
45
+ write_one(writer, object)
46
+ end
47
+ writer.pop
48
+ end
49
+
50
+ module JsonSerializerOptionsCompat
51
+ def add_attribute(value_from, key: nil, **options)
52
+ options[:as] ||= key if key
53
+
54
+ if (unless_proc = options.delete(:unless))
55
+ options[:if] = -> { !instance_exec(&unless_proc) }
56
+ end
57
+
58
+ super(value_from, **options)
59
+ end
60
+ end
61
+ end
62
+
63
+ require 'json_serializers'
64
+ require 'json_serializers/sugar'
65
+
66
+ JsonSerializer.singleton_class.prepend(ActiveModel::Serializer::JsonSerializerOptionsCompat)
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json_serializers/json_string_encoder'
4
+
5
+ # Internal: Allows to pass JSON serializers as options in `render`.
6
+ module JsonSerializers::ControllerSerialization
7
+ extend ActiveSupport::Concern
8
+ include ActionController::Renderers
9
+
10
+ # Internal: Allows to use JsonSerializer as `serializer` and `each_serializer`
11
+ # as with ActiveModelSerializers.
12
+ #
13
+ # render json: items, each_serializer: ItemSerializer
14
+ # render json: item, serializer: ItemSerializer
15
+ #
16
+ # NOTE: In practice, it should be preferable to simply do:
17
+ #
18
+ # render json: ItemSerializer.many(items)
19
+ # render json: ItemSerializer.one(item)
20
+ #
21
+ # which is more performant.
22
+ %i[_render_option_json _render_with_renderer_json].each do |renderer_method|
23
+ define_method renderer_method do |resource, options = {}|
24
+ serializer_class = options[:serializer] || options[:each_serializer]
25
+ if serializer_class && serializer_class < JsonSerializers::Serializer
26
+ super(JsonSerializers::JsonStringEncoder.encode_to_json(resource, **options), options.except(:root, :serializer, :each_serializer))
27
+ else
28
+ super(resource, **options)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Public: Contains utility functions to render objects to JSON.
4
+ #
5
+ # Useful to instantiate a single `JsonWriter` when rendering new serializers.
6
+ module JsonSerializers::JsonStringEncoder
7
+ class << self
8
+ # Public: Allows to use JsonSerializer in `serializer` and `each_serializer`
9
+ # as with ActiveModelSerializers.
10
+ # render json: items, each_serializer: ItemSerializer
11
+ # render json: item, serializer: ItemSerializer
12
+ #
13
+ # NOTE: Unlike the default encoder, this one will use the `root` option
14
+ # regardless of whether a serializer is specified or not.
15
+ #
16
+ # Returns a JSON string.
17
+ def encode_to_json(object, root: nil, serializer: nil, each_serializer: nil, **options)
18
+ result = if serializer
19
+ serializer.one(object, options)
20
+ elsif each_serializer
21
+ each_serializer.many(object, options)
22
+ elsif object.is_a?(String)
23
+ JsonSerializers::JsonValue.new(object)
24
+ else
25
+ object
26
+ end
27
+ Oj.dump(root ? { root => result } : result)
28
+ end
29
+
30
+ if JsonSerializers::Serializer::DEV_MODE
31
+ alias actual_encode_to_json encode_to_json
32
+ # Internal: Allows to detect misusage of the options during development.
33
+ def encode_to_json(object, root: nil, serializer: nil, each_serializer: nil, **options)
34
+ raise ArgumentError, 'You must use `each_serializer` when serializing collections' if serializer && serializer < JsonSerializers::Serializer && object.respond_to?(:map)
35
+ raise ArgumentError, 'You must use `serializer` when serializing a single object' if each_serializer && each_serializer < JsonSerializers::Serializer && !object.respond_to?(:map)
36
+
37
+ actual_encode_to_json(object, root: root, serializer: serializer, each_serializer: each_serializer, **options)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Public: Allows to prevent double encoding an existing JSON string.
4
+ #
5
+ # NOTE: Oj's raw_json option means there's no performance overhead, as it would
6
+ # occur with the previous alternative of parsing the JSON string.
7
+ class JsonSerializers::JsonValue
8
+ # Public: Expects json to be a JSON-encoded string.
9
+ def initialize(json)
10
+ @json = json
11
+ end
12
+
13
+ # Public: Expects an Array of JSON-encoded strings and wraps them in a JSON array.
14
+ #
15
+ # Returns a JsonValue representing a JSON-encoded array.
16
+ def self.array(json_rows)
17
+ new("[#{json_rows.join(',')}]")
18
+ end
19
+
20
+ # Public: Return the internal json when using string interpolation.
21
+ def to_s
22
+ @json
23
+ end
24
+
25
+ # Internal: Used by Oj::Rails::Encoder because we use the `raw_json` option.
26
+ def raw_json(*)
27
+ @json
28
+ end
29
+
30
+ # Internal: Used by Oj::Rails::Encoder when found inside a Hash or Array.
31
+ def as_json(_options = nil)
32
+ self
33
+ end
34
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Internal: Provides a simple API on top of Hash for memoization purposes.
4
+ class JsonSerializers::Memo
5
+ def initialize
6
+ @cache = {}
7
+ end
8
+
9
+ # Internal: Allows to clear the cache when binding the serializer to a
10
+ # different object.
11
+ def clear
12
+ @cache.clear
13
+ end
14
+
15
+ # Public: Allows to use a simple memoization pattern that also works for
16
+ # falsey values.
17
+ def fetch(key)
18
+ @cache.fetch(key) { @cache[key] = yield }
19
+ end
20
+ end