Merge branch '8784-dir-listings'
[arvados.git] / services / api / lib / serializers.rb
1 # Copyright (C) The Arvados Authors. All rights reserved.
2 #
3 # SPDX-License-Identifier: AGPL-3.0
4
5 require 'safe_json'
6
7 class Serializer
8   class TypeMismatch < ArgumentError
9   end
10
11   def self.dump(val)
12     if !val.is_a?(object_class)
13       raise TypeMismatch.new("cannot serialize #{val.class} as #{object_class}")
14     end
15     SafeJSON.dump(val)
16   end
17
18   def self.legacy_load(s)
19     val = Psych.safe_load(s)
20     if val.is_a? String
21       # If apiserver was downgraded to a YAML-only version after
22       # storing JSON in the database, the old code would have loaded
23       # the JSON document as a plain string, and then YAML-encoded
24       # it when saving it back to the database. It's too late now to
25       # make the old code behave better, but at least we can
26       # gracefully handle the mess it leaves in the database by
27       # double-decoding on the way out.
28       return SafeJSON.load(val)
29     else
30       return val
31     end
32   end
33
34   def self.load(s)
35     if s.nil?
36       object_class.new()
37     elsif s[0] == first_json_char
38       SafeJSON.load(s)
39     elsif s[0..2] == "---"
40       legacy_load(s)
41     else
42       raise "invalid serialized data #{s[0..5].inspect}"
43     end
44   end
45 end
46
47 class HashSerializer < Serializer
48   def self.first_json_char
49     "{"
50   end
51
52   def self.object_class
53     ::Hash
54   end
55 end
56
57 class ArraySerializer < Serializer
58   def self.first_json_char
59     "["
60   end
61
62   def self.object_class
63     ::Array
64   end
65 end