github.com/qiniu/go-sdk/v7@v7.27.0/internal/api-generator/json.go (about)

     1  package main
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  
     7  	"github.com/dave/jennifer/jen"
     8  	"github.com/iancoleman/strcase"
     9  	"gopkg.in/yaml.v3"
    10  )
    11  
    12  type (
    13  	JsonType struct {
    14  		String    bool
    15  		Integer   bool
    16  		Float     bool
    17  		Boolean   bool
    18  		Array     *JsonArray
    19  		Struct    *JsonStruct
    20  		Any       bool
    21  		StringMap bool
    22  	}
    23  
    24  	JsonArray struct {
    25  		Type          *JsonType `yaml:"type,omitempty"`
    26  		Name          string    `yaml:"name,omitempty"`
    27  		CamelCaseName string    `yaml:"camel_case_name,omitempty"`
    28  		SnakeCaseName string    `yaml:"snake_case_name,omitempty"`
    29  		Documentation string    `yaml:"documentation,omitempty"`
    30  	}
    31  
    32  	JsonStruct struct {
    33  		Fields        []JsonField `yaml:"fields,omitempty"`
    34  		Name          string      `yaml:"name,omitempty"`
    35  		CamelCaseName string      `yaml:"camel_case_name,omitempty"`
    36  		SnakeCaseName string      `yaml:"snake_case_name,omitempty"`
    37  		Documentation string      `yaml:"documentation,omitempty"`
    38  	}
    39  
    40  	JsonField struct {
    41  		Type               JsonType           `yaml:"type,omitempty"`
    42  		Key                string             `yaml:"key,omitempty"`
    43  		FieldName          string             `yaml:"field_name,omitempty"`
    44  		FieldCamelCaseName string             `yaml:"field_camel_case_name,omitempty"`
    45  		FieldSnakeCaseName string             `yaml:"field_snake_case_name,omitempty"`
    46  		Documentation      string             `yaml:"documentation,omitempty"`
    47  		Optional           *OptionalType      `yaml:"optional,omitempty"`
    48  		ServiceBucket      *ServiceBucketType `yaml:"service_bucket,omitempty"`
    49  		ServiceObject      *ServiceObjectType `yaml:"service_object,omitempty"`
    50  	}
    51  )
    52  
    53  func (jsonField *JsonField) camelCaseName() string {
    54  	if jsonField.FieldCamelCaseName != "" {
    55  		return jsonField.FieldCamelCaseName
    56  	}
    57  	return strcase.ToCamel(jsonField.FieldName)
    58  }
    59  
    60  func (jsonStruct *JsonStruct) camelCaseName() string {
    61  	if jsonStruct.CamelCaseName != "" {
    62  		return jsonStruct.CamelCaseName
    63  	}
    64  	return strcase.ToCamel(jsonStruct.Name)
    65  }
    66  
    67  func (jsonStruct *JsonStruct) addFields(group *jen.Group, includesJsonTag bool) error {
    68  	for _, field := range jsonStruct.Fields {
    69  		code, err := field.Type.AddTypeToStatement(jen.Id(field.camelCaseName()), field.Optional.ToOptionalType() == OptionalTypeNullable)
    70  		if err != nil {
    71  			return err
    72  		}
    73  		if includesJsonTag {
    74  			jsonTag := field.Key
    75  			switch field.Optional.ToOptionalType() {
    76  			case OptionalTypeOmitEmpty, OptionalTypeNullable:
    77  				jsonTag += ",omitempty"
    78  			}
    79  			code = code.Tag(map[string]string{"json": jsonTag})
    80  		}
    81  		if field.Documentation != "" {
    82  			code = code.Comment(field.Documentation)
    83  		}
    84  		group.Add(code)
    85  	}
    86  	return nil
    87  }
    88  
    89  func (jsonStruct *JsonStruct) addGetBucketNameFunc(group *jen.Group, structName string) (bool, error) {
    90  	field := jsonStruct.getServiceBucketField()
    91  
    92  	if field == nil || field.ServiceBucket.ToServiceBucketType() == ServiceBucketTypeNone {
    93  		return false, nil
    94  	} else if !field.Type.String {
    95  		panic("service bucket field must be string")
    96  	}
    97  
    98  	group.Add(jen.Func().
    99  		Params(jen.Id("j").Op("*").Id(structName)).
   100  		Id("getBucketName").
   101  		Params(jen.Id("ctx").Qual("context", "Context")).
   102  		Params(jen.String(), jen.Error()).
   103  		BlockFunc(func(group *jen.Group) {
   104  			fieldName := field.camelCaseName()
   105  			switch field.ServiceBucket.ToServiceBucketType() {
   106  			case ServiceBucketTypePlainText:
   107  				group.Add(jen.Return(jen.Id("j").Dot(fieldName), jen.Nil()))
   108  			case ServiceBucketTypeEntry:
   109  				group.Add(
   110  					jen.Return(
   111  						jen.Qual("strings", "SplitN").
   112  							Call(jen.Id("j").Dot(fieldName), jen.Lit(":"), jen.Lit(2)).
   113  							Index(jen.Lit(0)),
   114  						jen.Nil(),
   115  					),
   116  				)
   117  			case ServiceBucketTypeUploadToken:
   118  				group.Add(
   119  					jen.If(jen.Id("putPolicy"), jen.Err()).
   120  						Op(":=").
   121  						Qual(PackageNameUpToken, "NewParser").
   122  						Call(jen.Id("j").Dot(fieldName)).
   123  						Dot("GetPutPolicy").
   124  						Call(jen.Id("ctx")).
   125  						Op(";").
   126  						Err().
   127  						Op("!=").
   128  						Nil().
   129  						BlockFunc(func(group *jen.Group) {
   130  							group.Add(jen.Return(jen.Lit(""), jen.Err()))
   131  						}).
   132  						Else().
   133  						BlockFunc(func(group *jen.Group) {
   134  							group.Add(jen.Return(jen.Id("putPolicy").Dot("GetBucketName").Call()))
   135  						}),
   136  				)
   137  			default:
   138  				panic("unknown ServiceBucketType")
   139  			}
   140  		}))
   141  	return true, nil
   142  }
   143  
   144  func (jsonStruct *JsonStruct) addGetObjectNameFunc(group *jen.Group, structName string) (bool, error) {
   145  	field := jsonStruct.getServiceObjectField()
   146  
   147  	if field == nil || field.ServiceObject.ToServiceObjectType() == ServiceObjectTypeNone {
   148  		return false, nil
   149  	} else if !field.Type.String {
   150  		panic("service object field must be string")
   151  	}
   152  
   153  	group.Add(jen.Func().
   154  		Params(jen.Id("j").Op("*").Id(structName)).
   155  		Id("getObjectName").
   156  		Params().
   157  		Params(jen.String()).
   158  		BlockFunc(func(group *jen.Group) {
   159  			fieldName := field.camelCaseName()
   160  			switch field.ServiceObject.ToServiceObjectType() {
   161  			case ServiceObjectTypePlainText:
   162  				if field.Optional.ToOptionalType() == OptionalTypeNullable {
   163  					group.Add(jen.Var().Id("objectName").String())
   164  					group.Add(jen.If(jen.Id("j").Dot(fieldName).Op("!=").Nil()).BlockFunc(func(group *jen.Group) {
   165  						group.Add(jen.Id("objectName").Op("=").Op("*").Id("j").Dot(fieldName))
   166  					}))
   167  					group.Add(jen.Return(jen.Id("objectName")))
   168  				} else {
   169  					group.Return(jen.Id("j").Dot(fieldName))
   170  				}
   171  			case ServiceObjectTypeEntry:
   172  				group.Add(
   173  					jen.Id("parts").
   174  						Op(":=").
   175  						Qual("strings", "SplitN").
   176  						Call(jen.Id("j").Dot(fieldName), jen.Lit(":"), jen.Lit(2)))
   177  				group.Add(jen.If(jen.Len(jen.Id("parts")).Op(">").Lit(1)), jen.BlockFunc(func(group *jen.Group) {
   178  					group.Return(jen.Id("parts").Index(jen.Lit(1)))
   179  				}))
   180  				group.Add(jen.Return(jen.Lit("")))
   181  			default:
   182  				panic("unknown ServiceObjectType")
   183  			}
   184  		}))
   185  	return true, nil
   186  }
   187  
   188  func (jsonType *JsonType) generate(group *jen.Group, options CodeGeneratorOptions) error {
   189  	return jsonType.generateType(group, options, true, func() error {
   190  		if jsonType.Any {
   191  			return jsonType.addAnyJsonMarshalerUnmarshaler(group, options.camelCaseName())
   192  		}
   193  		return errors.New("base type could not be top level")
   194  	})
   195  }
   196  
   197  func (jsonType *JsonType) generateType(group *jen.Group, options CodeGeneratorOptions, topLevel bool, otherWise func() error) error {
   198  	if s := jsonType.Struct; s != nil {
   199  		if err := s.generate(group, options, topLevel); err != nil {
   200  			return err
   201  		}
   202  		return nil
   203  	} else if a := jsonType.Array; a != nil {
   204  		if err := a.generate(group, options, topLevel); err != nil {
   205  			return err
   206  		}
   207  		return nil
   208  	}
   209  	return otherWise()
   210  }
   211  
   212  func (jsonType *JsonType) AddTypeToStatement(statement *jen.Statement, nilable bool) (*jen.Statement, error) {
   213  	if nilable {
   214  		statement = statement.Op("*")
   215  	}
   216  	if jsonType.String {
   217  		return statement.String(), nil
   218  	} else if jsonType.Integer {
   219  		return statement.Int64(), nil
   220  	} else if jsonType.Float {
   221  		return statement.Float64(), nil
   222  	} else if jsonType.Boolean {
   223  		return statement.Bool(), nil
   224  	} else if jsonType.Any {
   225  		return statement.Interface(), nil
   226  	} else if jsonType.StringMap {
   227  		return statement.Map(jen.String()).String(), nil
   228  	} else if jsonType.Array != nil {
   229  		return statement.Id(jsonType.Array.camelCaseName()), nil
   230  	} else if jsonType.Struct != nil {
   231  		return statement.Id(jsonType.Struct.camelCaseName()), nil
   232  	} else {
   233  		return nil, errors.New("unknown type")
   234  	}
   235  }
   236  
   237  func (jsonType *JsonType) ZeroValue() interface{} {
   238  	if jsonType.String {
   239  		return ""
   240  	} else if jsonType.Integer {
   241  		return 0
   242  	} else if jsonType.Float {
   243  		return 0.0
   244  	} else if jsonType.Boolean {
   245  		return false
   246  	} else {
   247  		return nil
   248  	}
   249  }
   250  
   251  func (jsonType *JsonType) addAnyJsonMarshalerUnmarshaler(group *jen.Group, structName string) (err error) {
   252  	group.Add(
   253  		jen.Func().
   254  			Params(jen.Id("j").Op("*").Id(structName)).
   255  			Id("MarshalJSON").
   256  			Params().
   257  			Params(jen.Index().Byte(), jen.Error()).
   258  			BlockFunc(func(group *jen.Group) {
   259  				group.Add(jen.Return(
   260  					jen.Qual("encoding/json", "Marshal").
   261  						Call(jen.Id("j").Dot("Body")),
   262  				))
   263  			}),
   264  	)
   265  	group.Add(
   266  		jen.Func().
   267  			Params(jen.Id("j").Op("*").Id(structName)).
   268  			Id("UnmarshalJSON").
   269  			Params(jen.Id("data").Index().Byte()).
   270  			Params(jen.Error()).
   271  			BlockFunc(func(group *jen.Group) {
   272  				group.Return().Qual("encoding/json", "Unmarshal").Call(jen.Id("data"), jen.Op("&").Id("j").Dot("Body"))
   273  			}),
   274  	)
   275  	return
   276  }
   277  
   278  func (jsonArray *JsonArray) camelCaseName() string {
   279  	if jsonArray.CamelCaseName != "" {
   280  		return jsonArray.CamelCaseName
   281  	}
   282  	return strcase.ToCamel(jsonArray.Name)
   283  }
   284  
   285  func (jsonArray *JsonArray) addFields(group *jen.Group) error {
   286  	code := jen.Id(jsonArray.camelCaseName()).Id(jsonArray.camelCaseName())
   287  	if jsonArray.Documentation != "" {
   288  		code = code.Comment(jsonArray.Documentation)
   289  	}
   290  	group.Add(code)
   291  	return nil
   292  }
   293  
   294  func (jsonArray *JsonArray) generate(group *jen.Group, options CodeGeneratorOptions, topLevel bool) (err error) {
   295  	if err = jsonArray.Type.generateType(group, CodeGeneratorOptions{}, false, func() error {
   296  		return nil
   297  	}); err != nil {
   298  		return
   299  	}
   300  
   301  	if jsonArray.Documentation != "" {
   302  		group.Add(jen.Comment(jsonArray.Documentation))
   303  	}
   304  	code := jen.Type().Id(jsonArray.camelCaseName())
   305  	if !topLevel {
   306  		code = code.Op("=")
   307  	}
   308  	code = code.Index()
   309  	code, err = jsonArray.Type.AddTypeToStatement(code, false)
   310  	if err != nil {
   311  		return
   312  	}
   313  	group.Add(code)
   314  	if topLevel {
   315  		if err = jsonArray.addJsonMarshalerUnmarshaler(group, options.camelCaseName()); err != nil {
   316  			return
   317  		}
   318  	}
   319  
   320  	return
   321  }
   322  
   323  func (jsonArray *JsonArray) addJsonMarshalerUnmarshaler(group *jen.Group, structName string) (err error) {
   324  	fieldName := jsonArray.camelCaseName()
   325  	group.Add(
   326  		jen.Func().
   327  			Params(jen.Id("j").Op("*").Id(structName)).
   328  			Id("MarshalJSON").
   329  			Params().
   330  			Params(jen.Index().Byte(), jen.Error()).
   331  			BlockFunc(func(group *jen.Group) {
   332  				group.Add(jen.Return(
   333  					jen.Qual("encoding/json", "Marshal").
   334  						Call(jen.Id("j").Dot(fieldName)),
   335  				))
   336  			}),
   337  	)
   338  	group.Add(
   339  		jen.Func().
   340  			Params(jen.Id("j").Op("*").Id(structName)).
   341  			Id("UnmarshalJSON").
   342  			Params(jen.Id("data").Index().Byte()).
   343  			Params(jen.Error()).
   344  			BlockFunc(func(group *jen.Group) {
   345  				group.Add(jen.Var().Id("array").Id(fieldName))
   346  				group.Add(
   347  					jen.If(
   348  						jen.Err().Op(":=").Qual("encoding/json", "Unmarshal").Call(jen.Id("data"), jen.Op("&").Id("array")),
   349  						jen.Err().Op("!=").Nil(),
   350  					).BlockFunc(func(group *jen.Group) {
   351  						group.Return(jen.Err())
   352  					}),
   353  				)
   354  				group.Add(jen.Id("j").Dot(fieldName).Op("=").Id("array"))
   355  				group.Add(jen.Return(jen.Nil()))
   356  			}),
   357  	)
   358  	return
   359  }
   360  
   361  func (jsonStruct *JsonStruct) generate(group *jen.Group, options CodeGeneratorOptions, topLevel bool) (err error) {
   362  	for _, field := range jsonStruct.Fields {
   363  		if err = field.Type.generateType(group, CodeGeneratorOptions{
   364  			Name:          field.FieldName,
   365  			CamelCaseName: field.FieldCamelCaseName,
   366  			SnakeCaseName: field.FieldSnakeCaseName,
   367  			Documentation: field.Documentation,
   368  		}, false, func() error {
   369  			return nil
   370  		}); err != nil {
   371  			return
   372  		}
   373  	}
   374  
   375  	opts := make([]CodeGeneratorOptions, 0, 2)
   376  	if options.camelCaseName() != "" {
   377  		opts = append(opts, options)
   378  	}
   379  	if jsonStruct.camelCaseName() != "" && options.camelCaseName() != jsonStruct.camelCaseName() {
   380  		opts = append(opts, CodeGeneratorOptions{
   381  			Name:          jsonStruct.Name,
   382  			CamelCaseName: jsonStruct.CamelCaseName,
   383  			SnakeCaseName: jsonStruct.SnakeCaseName,
   384  			Documentation: jsonStruct.Documentation,
   385  		})
   386  	}
   387  	if len(opts) == 0 {
   388  		return errors.New("unknown struct name")
   389  	}
   390  
   391  	if !topLevel {
   392  		if opts[0].Documentation != "" {
   393  			group.Add(jen.Comment(opts[0].Documentation))
   394  		}
   395  		group.Add(jen.Type().Id(opts[0].camelCaseName()).StructFunc(func(group *jen.Group) {
   396  			err = jsonStruct.addFields(group, false)
   397  		}))
   398  		if err != nil {
   399  			return
   400  		}
   401  	}
   402  
   403  	if len(opts) > 1 {
   404  		if opts[1].Documentation != "" {
   405  			group.Add(jen.Comment(opts[1].Documentation))
   406  		}
   407  		group.Add(jen.Type().Id(opts[1].camelCaseName()).Op("=").Id(opts[0].camelCaseName()))
   408  	}
   409  
   410  	if err = jsonStruct.addJsonMarshalerUnmarshaler(group, opts[0].camelCaseName()); err != nil {
   411  		return
   412  	}
   413  	if err = jsonStruct.generateValidateFunc(group, opts[0].camelCaseName()); err != nil {
   414  		return
   415  	}
   416  
   417  	return
   418  }
   419  
   420  func (jsonStruct *JsonStruct) addJsonMarshalerUnmarshaler(group *jen.Group, structName string) (err error) {
   421  	group.Add(jen.Type().Id("json" + structName).StructFunc(func(group *jen.Group) {
   422  		err = jsonStruct.addFields(group, true)
   423  	}))
   424  	if err != nil {
   425  		return
   426  	}
   427  	group.Add(
   428  		jen.Func().
   429  			Params(jen.Id("j").Op("*").Id(structName)).
   430  			Id("MarshalJSON").
   431  			Params().
   432  			Params(jen.Index().Byte(), jen.Error()).
   433  			BlockFunc(func(group *jen.Group) {
   434  				group.Add(jen.If(
   435  					jen.Err().Op(":=").Id("j").Dot("validate").Call(),
   436  					jen.Err().Op("!=").Nil(),
   437  				).BlockFunc(func(group *jen.Group) {
   438  					group.Return(jen.Nil(), jen.Err())
   439  				}))
   440  				group.Add(jen.Return(
   441  					jen.Qual("encoding/json", "Marshal").
   442  						Call(
   443  							jen.Op("&").Id("json" + structName).
   444  								ValuesFunc(func(group *jen.Group) {
   445  									for _, field := range jsonStruct.Fields {
   446  										fieldName := field.camelCaseName()
   447  										group.Add(jen.Id(fieldName).Op(":").Id("j").Dot(fieldName))
   448  									}
   449  								}),
   450  						),
   451  				))
   452  			}),
   453  	)
   454  	group.Add(
   455  		jen.Func().
   456  			Params(jen.Id("j").Op("*").Id(structName)).
   457  			Id("UnmarshalJSON").
   458  			Params(jen.Id("data").Index().Byte()).
   459  			Params(jen.Error()).
   460  			BlockFunc(func(group *jen.Group) {
   461  				group.Add(jen.Var().Id("nj").Id("json" + structName))
   462  				group.Add(
   463  					jen.If(
   464  						jen.Err().Op(":=").Qual("encoding/json", "Unmarshal").Call(jen.Id("data"), jen.Op("&").Id("nj")),
   465  						jen.Err().Op("!=").Nil(),
   466  					).BlockFunc(func(group *jen.Group) {
   467  						group.Return(jen.Err())
   468  					}),
   469  				)
   470  				for _, field := range jsonStruct.Fields {
   471  					fieldName := field.camelCaseName()
   472  					group.Add(jen.Id("j").Dot(fieldName).Op("=").Id("nj").Dot(fieldName))
   473  				}
   474  				group.Add(jen.Return(jen.Nil()))
   475  			}),
   476  	)
   477  	return
   478  }
   479  
   480  func (jsonStruct *JsonStruct) generateValidateFunc(group *jen.Group, structName string) error {
   481  	group.Add(jen.Func().
   482  		Params(jen.Id("j").Op("*").Id(structName)).
   483  		Id("validate").
   484  		Params().
   485  		Params(jen.Error()).
   486  		BlockFunc(func(group *jen.Group) {
   487  			for _, field := range jsonStruct.Fields {
   488  				if field.Optional.ToOptionalType() == OptionalTypeRequired {
   489  					var cond *jen.Statement
   490  					fieldName := field.camelCaseName()
   491  					if field.Type.String || field.Type.Integer || field.Type.Float {
   492  						cond = jen.Id("j").Dot(fieldName).Op("==").Lit(field.Type.ZeroValue())
   493  					} else if field.Type.Boolean {
   494  						// do nothing
   495  					} else if field.Type.Array != nil {
   496  						cond = jen.Len(jen.Id("j").Dot(fieldName)).Op("==").Lit(0)
   497  					} else if field.Type.Struct != nil {
   498  						// do nothing
   499  					} else {
   500  						cond = jen.Id("j").Dot(fieldName).Op("==").Nil()
   501  					}
   502  					if cond != nil {
   503  						group.Add(jen.If(cond).BlockFunc(func(group *jen.Group) {
   504  							group.Add(jen.Return(
   505  								jen.Qual(PackageNameErrors, "MissingRequiredFieldError").
   506  									ValuesFunc(func(group *jen.Group) {
   507  										group.Add(jen.Id("Name").Op(":").Lit(fieldName))
   508  									}),
   509  							))
   510  						}))
   511  					}
   512  					if arrayField := field.Type.Array; arrayField != nil {
   513  						if arrayField.Type.Struct != nil {
   514  							group.Add(
   515  								jen.For(jen.List(jen.Id("_"), jen.Id("value")).Op(":=").Range().Id("j").Dot(fieldName)).
   516  									BlockFunc(func(group *jen.Group) {
   517  										group.Add(
   518  											jen.If(
   519  												jen.Err().Op(":=").Id("value").Dot("validate").Call(),
   520  												jen.Err().Op("!=").Nil(),
   521  											).BlockFunc(func(group *jen.Group) {
   522  												group.Return(jen.Err())
   523  											}),
   524  										)
   525  									}),
   526  							)
   527  						}
   528  					} else if field.Type.Struct != nil {
   529  						group.Add(
   530  							jen.If(
   531  								jen.Err().Op(":=").Id("j").Dot(fieldName).Dot("validate").Call(),
   532  								jen.Err().Op("!=").Nil(),
   533  							).BlockFunc(func(group *jen.Group) {
   534  								group.Return(jen.Err())
   535  							}),
   536  						)
   537  					}
   538  				}
   539  			}
   540  			group.Add(jen.Return(jen.Nil()))
   541  		}))
   542  	return nil
   543  }
   544  
   545  func (jsonStruct *JsonStruct) getServiceBucketField() *JsonField {
   546  	var serviceBucketField *JsonField = nil
   547  
   548  	for i := range jsonStruct.Fields {
   549  		if jsonStruct.Fields[i].ServiceBucket.ToServiceBucketType() != ServiceBucketTypeNone {
   550  			if serviceBucketField == nil {
   551  				serviceBucketField = &jsonStruct.Fields[i]
   552  			} else {
   553  				panic("multiple service bucket fields")
   554  			}
   555  		}
   556  	}
   557  	return serviceBucketField
   558  }
   559  
   560  func (jsonStruct *JsonStruct) getServiceObjectField() *JsonField {
   561  	var serviceObjectField *JsonField = nil
   562  
   563  	for i := range jsonStruct.Fields {
   564  		if jsonStruct.Fields[i].ServiceObject.ToServiceObjectType() != ServiceObjectTypeNone {
   565  			if serviceObjectField == nil {
   566  				serviceObjectField = &jsonStruct.Fields[i]
   567  			} else {
   568  				panic("multiple service object fields")
   569  			}
   570  		}
   571  	}
   572  	return serviceObjectField
   573  }
   574  
   575  func (jsonType *JsonType) UnmarshalYAML(value *yaml.Node) error {
   576  	switch value.ShortTag() {
   577  	case "!!str":
   578  		switch value.Value {
   579  		case "string":
   580  			jsonType.String = true
   581  		case "integer":
   582  			jsonType.Integer = true
   583  		case "float":
   584  			jsonType.Float = true
   585  		case "boolean":
   586  			jsonType.Boolean = true
   587  		case "any":
   588  			jsonType.Any = true
   589  		case "string_map":
   590  			jsonType.StringMap = true
   591  		default:
   592  			return fmt.Errorf("unknown json type: %s", value.Value)
   593  		}
   594  		return nil
   595  	case "!!map":
   596  		switch value.Content[0].Value {
   597  		case "array":
   598  			return value.Content[1].Decode(&jsonType.Array)
   599  		case "struct":
   600  			return value.Content[1].Decode(&jsonType.Struct)
   601  		default:
   602  			return fmt.Errorf("unknown json type: %s", value.Content[0].Value)
   603  		}
   604  	default:
   605  		return fmt.Errorf("unknown json type: %s", value.ShortTag())
   606  	}
   607  }