def _generate_struct(self, struct): with self.block('type %s struct' % struct.name): if struct.parent_type: self.emit( fmt_type(struct.parent_type, struct.namespace).lstrip('*')) for field in struct.fields: self._generate_field(field, namespace=struct.namespace) if struct.name in ('DownloadArg', ): self.emit( '// ExtraHeaders can be used to pass Range, If-None-Match headers' ) self.emit('ExtraHeaders map[string]string `json:"-"`') self._generate_struct_builder(struct) self.emit() if needs_base_type(struct): self.emit('// UnmarshalJSON deserializes into a %s instance' % struct.name) with self.block('func (u *%s) UnmarshalJSON(b []byte) error' % struct.name): with self.block('type wrap struct'): for field in struct.all_fields: self._generate_field(field, namespace=struct.namespace, raw=_needs_base_type( field.data_type)) self.emit('var w wrap') with self.block('if err := json.Unmarshal(b, &w); err != nil'): self.emit('return err') for field in struct.all_fields: dt = field.data_type fn = fmt_var(field.name) tn = fmt_type(dt, namespace=struct.namespace, use_interface=True) if _needs_base_type(dt): if is_list_type(dt): self.emit("u.{0} = make({1}, len(w.{0}))".format( fn, tn)) # Grab the underlying type to get the correct Is...FromJSON method tn = fmt_type(dt.data_type, namespace=struct.namespace, use_interface=True) with self.block( "for i, e := range w.{0}".format(fn)): self.emit("v, err := {1}FromJSON(e)".format( fn, tn)) with self.block('if err != nil'): self.emit('return err') self.emit("u.{0}[i] = v".format(fn)) else: self.emit("{0}, err := {1}FromJSON(w.{0})".format( fn, tn)) with self.block('if err != nil'): self.emit('return err') self.emit("u.{0} = {0}".format(fn)) else: self.emit("u.{0} = w.{0}".format(fn)) self.emit('return nil')
def _generate_union_helper(self, u): name = u.name namespace = u.namespace # Unions can be inherited, but don't need to be polymorphic. # So let's flatten out all the inherited fields. fields = u.all_fields if is_struct_type(u) and u.has_enumerated_subtypes(): name = fmt_var(name, export=False) + 'Union' fields = u.get_enumerated_subtypes() with self.block('type %s struct' % name): self.emit('dropbox.Tagged') for field in fields: if is_void_type(field.data_type): continue self._generate_field(field, union_field=True, namespace=namespace) self.emit() self.emit('// Valid tag values for %s' % fmt_var(u.name)) with self.block('const', delim=('(', ')')): for field in fields: self.emit('%s%s = "%s"' % (fmt_var(u.name), fmt_var(field.name), field.name)) self.emit() num_void_fields = sum([is_void_type(f.data_type) for f in fields]) # Simple structure, no need in UnmarshalJSON if len(fields) == num_void_fields: return self.emit('// UnmarshalJSON deserializes into a %s instance' % name) with self.block('func (u *%s) UnmarshalJSON(body []byte) error' % name): with self.block('type wrap struct'): self.emit('dropbox.Tagged') for field in fields: if is_void_type(field.data_type) or ( is_struct_type(field.data_type) and not _needs_base_type(field.data_type)): # pure structures are flattened in the containing union json blob and thus are loaded from body continue # sub-unions must be handled as RawMessage, which will be loaded into correct implementation later self._generate_field(field, union_field=True, namespace=namespace, raw=_needs_base_type(field.data_type)) self.emit('var w wrap') self.emit('var err error') with self.block('if err = json.Unmarshal(body, &w); err != nil'): self.emit('return err') self.emit('u.Tag = w.Tag') with self.block('switch u.Tag'): for field in fields: if is_void_type(field.data_type): continue field_name = fmt_var(field.name) with self.block('case "%s":' % field.name, delim=(None, None)): if _needs_base_type(field.data_type): self.emit("u.{0}, err = Is{1}FromJSON(w.{0})" .format(field_name, field.data_type.name)) elif is_struct_type(field.data_type): self.emit('err = json.Unmarshal(body, &u.{0})' .format(field_name)) else: self.emit('u.{0} = w.{0}'.format(field_name)) with self.block("if err != nil"): self.emit("return err") self.emit('return nil') self.emit()