diff --git a/gen/decoder.go b/gen/decoder.go index d52b504..0688e5d 100644 --- a/gen/decoder.go +++ b/gen/decoder.go @@ -123,6 +123,41 @@ func (g *Generator) genTypeDecoderNoCheck(t reflect.Type, out string, tags field fmt.Fprintln(g.out, ws+"}") } + case reflect.Array: + iterVar := g.uniqueVarName() + elem := t.Elem() + + if elem.Kind() == reflect.Uint8 { + fmt.Fprintln(g.out, ws+"if in.IsNull() {") + fmt.Fprintln(g.out, ws+" in.Skip()") + fmt.Fprintln(g.out, ws+"} else {") + fmt.Fprintln(g.out, ws+" copy("+out+"[:], in.Bytes())") + fmt.Fprintln(g.out, ws+"}") + + } else { + + length := t.Len() + + fmt.Fprintln(g.out, ws+"if in.IsNull() {") + fmt.Fprintln(g.out, ws+" in.Skip()") + fmt.Fprintln(g.out, ws+"} else {") + fmt.Fprintln(g.out, ws+" in.Delim('[')") + fmt.Fprintln(g.out, ws+" "+iterVar+" := 0") + fmt.Fprintln(g.out, ws+" for !in.IsDelim(']') {") + fmt.Fprintln(g.out, ws+" if "+iterVar+" < "+fmt.Sprint(length)+" {") + + g.genTypeDecoder(elem, out+"["+iterVar+"]", tags, indent+3) + + fmt.Fprintln(g.out, ws+" "+iterVar+"++") + fmt.Fprintln(g.out, ws+" } else {") + fmt.Fprintln(g.out, ws+" in.SkipRecursive()") + fmt.Fprintln(g.out, ws+" }") + fmt.Fprintln(g.out, ws+" in.WantComma()") + fmt.Fprintln(g.out, ws+" }") + fmt.Fprintln(g.out, ws+" in.Delim(']')") + fmt.Fprintln(g.out, ws+"}") + } + case reflect.Struct: dec := g.getDecoderName(t) g.addType(t) @@ -287,16 +322,16 @@ func getStructFields(t reflect.Type) ([]reflect.StructField, error) { func (g *Generator) genDecoder(t reflect.Type) error { switch t.Kind() { - case reflect.Slice: - return g.genSliceDecoder(t) + case reflect.Slice, reflect.Array: + return g.genSliceArrayDecoder(t) default: return g.genStructDecoder(t) } } -func (g *Generator) genSliceDecoder(t reflect.Type) error { - if t.Kind() != reflect.Slice { - return fmt.Errorf("cannot generate encoder/decoder for %v, not a slice type", t) +func (g *Generator) genSliceArrayDecoder(t reflect.Type) error { + if t.Kind() != reflect.Slice && t.Kind() != reflect.Array { + return fmt.Errorf("cannot generate encoder/decoder for %v, not a slice or array type", t) } fname := g.getDecoderName(t) @@ -378,8 +413,8 @@ func (g *Generator) genStructDecoder(t reflect.Type) error { } func (g *Generator) genStructUnmarshaller(t reflect.Type) error { - if t.Kind() != reflect.Struct && t.Kind() != reflect.Slice { - return fmt.Errorf("cannot generate encoder/decoder for %v, not a struct/slice type", t) + if t.Kind() != reflect.Struct && t.Kind() != reflect.Slice && t.Kind() != reflect.Array { + return fmt.Errorf("cannot generate encoder/decoder for %v, not a struct/slice/array type", t) } fname := g.getDecoderName(t) diff --git a/gen/encoder.go b/gen/encoder.go index 55b12ff..ba9053f 100644 --- a/gen/encoder.go +++ b/gen/encoder.go @@ -137,6 +137,25 @@ func (g *Generator) genTypeEncoderNoCheck(t reflect.Type, in string, tags fieldT fmt.Fprintln(g.out, ws+"}") } + case reflect.Array: + elem := t.Elem() + iVar := g.uniqueVarName() + + if t.Elem().Kind() == reflect.Uint8 { + fmt.Fprintln(g.out, ws+"out.Base64Bytes("+in+"[:])") + } else { + fmt.Fprintln(g.out, ws+"out.RawByte('[')") + fmt.Fprintln(g.out, ws+"for "+iVar+" := range "+in+" {") + fmt.Fprintln(g.out, ws+" if "+iVar+" > 0 {") + fmt.Fprintln(g.out, ws+" out.RawByte(',')") + fmt.Fprintln(g.out, ws+" }") + + g.genTypeEncoder(elem, in+"["+iVar+"]", tags, indent+1) + + fmt.Fprintln(g.out, ws+"}") + fmt.Fprintln(g.out, ws+"out.RawByte(']')") + } + case reflect.Struct: enc := g.getEncoderName(t) g.addType(t) @@ -214,6 +233,7 @@ func (g *Generator) notEmptyCheck(t reflect.Type, v string) string { return v + " != 0" default: + // note: Array types don't have a useful empty value return "true" } } @@ -246,16 +266,16 @@ func (g *Generator) genStructFieldEncoder(t reflect.Type, f reflect.StructField) func (g *Generator) genEncoder(t reflect.Type) error { switch t.Kind() { - case reflect.Slice: - return g.genSliceEncoder(t) + case reflect.Slice, reflect.Array: + return g.genSliceArrayEncoder(t) default: return g.genStructEncoder(t) } } -func (g *Generator) genSliceEncoder(t reflect.Type) error { - if t.Kind() != reflect.Slice { - return fmt.Errorf("cannot generate encoder/decoder for %v, not a slice type", t) +func (g *Generator) genSliceArrayEncoder(t reflect.Type) error { + if t.Kind() != reflect.Slice && t.Kind() != reflect.Array { + return fmt.Errorf("cannot generate encoder/decoder for %v, not a slice or array type", t) } fname := g.getEncoderName(t) @@ -300,8 +320,8 @@ func (g *Generator) genStructEncoder(t reflect.Type) error { } func (g *Generator) genStructMarshaller(t reflect.Type) error { - if t.Kind() != reflect.Struct && t.Kind() != reflect.Slice { - return fmt.Errorf("cannot generate encoder/decoder for %v, not a struct/slice type", t) + if t.Kind() != reflect.Struct && t.Kind() != reflect.Slice && t.Kind() != reflect.Array { + return fmt.Errorf("cannot generate encoder/decoder for %v, not a struct/slice/array type", t) } fname := g.getEncoderName(t) diff --git a/gen/generator.go b/gen/generator.go index 2a3ef9c..1c527d5 100644 --- a/gen/generator.go +++ b/gen/generator.go @@ -8,6 +8,7 @@ import ( "path" "reflect" "sort" + "strconv" "strings" "unicode" ) @@ -233,6 +234,8 @@ func (g *Generator) getType(t reflect.Type) string { return "*" + g.getType(t.Elem()) case reflect.Slice: return "[]" + g.getType(t.Elem()) + case reflect.Array: + return "[" + strconv.Itoa(t.Len()) + "]" + g.getType(t.Elem()) case reflect.Map: return "map[" + g.getType(t.Key()) + "]" + g.getType(t.Elem()) } diff --git a/tests/basic_test.go b/tests/basic_test.go index a15253a..7e454ae 100644 --- a/tests/basic_test.go +++ b/tests/basic_test.go @@ -31,6 +31,7 @@ var testCases = []struct { {&unexportedStructValue, unexportedStructString}, {&excludedFieldValue, excludedFieldString}, {&sliceValue, sliceString}, + {&arrayValue, arrayString}, {&mapsValue, mapsString}, {&deepNestValue, deepNestString}, {&IntsValue, IntsString}, diff --git a/tests/data.go b/tests/data.go index 06298c2..1694a55 100644 --- a/tests/data.go +++ b/tests/data.go @@ -445,6 +445,27 @@ var sliceString = `{` + `"NilIntSlice":null` + `}` +type Arrays struct { + ByteArray [3]byte + EmptyByteArray [0]byte + IntArray [5]int + EmptyIntArray [0]int +} + +var arrayValue = Arrays{ + ByteArray: [3]byte{'a', 'b', 'c'}, + EmptyByteArray: [0]byte{}, + IntArray: [5]int{1, 2, 3, 4, 5}, + EmptyIntArray: [0]int{}, +} + +var arrayString = `{` + + `"ByteArray":"YWJj",` + + `"EmptyByteArray":"",` + + `"IntArray":[1,2,3,4,5],` + + `"EmptyIntArray":[]` + + `}` + type Str string type Maps struct {