// generated by jwg -output misc/fixture/j/model_json.go misc/fixture/j; DO NOT EDIT

package j

import (
	"encoding/json"
)

// FooJSON is jsonized struct for Foo.
type FooJSON struct {
	Tmp       *Temp `json:"tmp,omitempty"`
	Bar       `json:",omitempty"`
	*Buzz     `json:",omitempty"`
	HogeJSON  `json:",omitempty"`
	*FugaJSON `json:",omitempty"`
}

// FooJSONList is synonym about []*FooJSON.
type FooJSONList []*FooJSON

// FooPropertyEncoder is property encoder for [1]sJSON.
type FooPropertyEncoder func(src *Foo, dest *FooJSON) error

// FooPropertyDecoder is property decoder for [1]sJSON.
type FooPropertyDecoder func(src *FooJSON, dest *Foo) error

// FooPropertyInfo stores property information.
type FooPropertyInfo struct {
	fieldName string
	jsonName  string
	Encoder   FooPropertyEncoder
	Decoder   FooPropertyDecoder
}

// FieldName returns struct field name of property.
func (info *FooPropertyInfo) FieldName() string {
	return info.fieldName
}

// JSONName returns json field name of property.
func (info *FooPropertyInfo) JSONName() string {
	return info.jsonName
}

// FooJSONBuilder convert between Foo to FooJSON mutually.
type FooJSONBuilder struct {
	_properties        map[string]*FooPropertyInfo
	_jsonPropertyMap   map[string]*FooPropertyInfo
	_structPropertyMap map[string]*FooPropertyInfo
	Tmp                *FooPropertyInfo
	Bar                *FooPropertyInfo
	Buzz               *FooPropertyInfo
	Hoge               *FooPropertyInfo
	Fuga               *FooPropertyInfo
}

// NewFooJSONBuilder make new FooJSONBuilder.
func NewFooJSONBuilder() *FooJSONBuilder {
	jb := &FooJSONBuilder{
		_properties:        map[string]*FooPropertyInfo{},
		_jsonPropertyMap:   map[string]*FooPropertyInfo{},
		_structPropertyMap: map[string]*FooPropertyInfo{},
		Tmp: &FooPropertyInfo{
			fieldName: "Tmp",
			jsonName:  "tmp",
			Encoder: func(src *Foo, dest *FooJSON) error {
				if src == nil {
					return nil
				}
				dest.Tmp = src.Tmp
				return nil
			},
			Decoder: func(src *FooJSON, dest *Foo) error {
				if src == nil {
					return nil
				}
				dest.Tmp = src.Tmp
				return nil
			},
		},
		Bar: &FooPropertyInfo{
			fieldName: "Bar",
			jsonName:  "",
			Encoder: func(src *Foo, dest *FooJSON) error {
				if src == nil {
					return nil
				}
				dest.Bar = src.Bar
				return nil
			},
			Decoder: func(src *FooJSON, dest *Foo) error {
				if src == nil {
					return nil
				}
				dest.Bar = src.Bar
				return nil
			},
		},
		Buzz: &FooPropertyInfo{
			fieldName: "Buzz",
			jsonName:  "",
			Encoder: func(src *Foo, dest *FooJSON) error {
				if src == nil {
					return nil
				}
				dest.Buzz = src.Buzz
				return nil
			},
			Decoder: func(src *FooJSON, dest *Foo) error {
				if src == nil {
					return nil
				}
				dest.Buzz = src.Buzz
				return nil
			},
		},
		Hoge: &FooPropertyInfo{
			fieldName: "Hoge",
			jsonName:  "",
			Encoder: func(src *Foo, dest *FooJSON) error {
				if src == nil {
					return nil
				}
				d, err := NewHogeJSONBuilder().AddAll().Convert(&src.Hoge)
				if err != nil {
					return err
				}
				dest.HogeJSON = *d
				return nil
			},
			Decoder: func(src *FooJSON, dest *Foo) error {
				if src == nil {
					return nil
				}
				d, err := src.HogeJSON.Convert()
				if err != nil {
					return err
				}
				dest.Hoge = *d
				return nil
			},
		},
		Fuga: &FooPropertyInfo{
			fieldName: "Fuga",
			jsonName:  "",
			Encoder: func(src *Foo, dest *FooJSON) error {
				if src == nil {
					return nil
				} else if src.Fuga == nil {
					return nil
				}
				d, err := NewFugaJSONBuilder().AddAll().Convert(src.Fuga)
				if err != nil {
					return err
				}
				dest.FugaJSON = d
				return nil
			},
			Decoder: func(src *FooJSON, dest *Foo) error {
				if src == nil {
					return nil
				} else if src.FugaJSON == nil {
					return nil
				}
				d, err := src.FugaJSON.Convert()
				if err != nil {
					return err
				}
				dest.Fuga = d
				return nil
			},
		},
	}
	jb._structPropertyMap["Tmp"] = jb.Tmp
	jb._jsonPropertyMap["tmp"] = jb.Tmp
	jb._structPropertyMap["Bar"] = jb.Bar
	jb._jsonPropertyMap[""] = jb.Bar
	jb._structPropertyMap["Buzz"] = jb.Buzz
	jb._jsonPropertyMap[""] = jb.Buzz
	jb._structPropertyMap["Hoge"] = jb.Hoge
	jb._jsonPropertyMap[""] = jb.Hoge
	jb._structPropertyMap["Fuga"] = jb.Fuga
	jb._jsonPropertyMap[""] = jb.Fuga
	return jb
}

// Properties returns all properties on FooJSONBuilder.
func (b *FooJSONBuilder) Properties() []*FooPropertyInfo {
	return []*FooPropertyInfo{
		b.Tmp,
		b.Bar,
		b.Buzz,
		b.Hoge,
		b.Fuga,
	}
}

// AddAll adds all property to FooJSONBuilder.
func (b *FooJSONBuilder) AddAll() *FooJSONBuilder {
	b._properties["Tmp"] = b.Tmp
	b._properties["Bar"] = b.Bar
	b._properties["Buzz"] = b.Buzz
	b._properties["Hoge"] = b.Hoge
	b._properties["Fuga"] = b.Fuga
	return b
}

// Add specified property to FooJSONBuilder.
func (b *FooJSONBuilder) Add(info *FooPropertyInfo) *FooJSONBuilder {
	b._properties[info.fieldName] = info
	return b
}

// AddByJSONNames add properties to FooJSONBuilder by JSON property name. if name is not in the builder, it will ignore.
func (b *FooJSONBuilder) AddByJSONNames(names ...string) *FooJSONBuilder {
	for _, name := range names {
		info := b._jsonPropertyMap[name]
		if info == nil {
			continue
		}
		b._properties[info.fieldName] = info
	}
	return b
}

// AddByNames add properties to FooJSONBuilder by struct property name. if name is not in the builder, it will ignore.
func (b *FooJSONBuilder) AddByNames(names ...string) *FooJSONBuilder {
	for _, name := range names {
		info := b._structPropertyMap[name]
		if info == nil {
			continue
		}
		b._properties[info.fieldName] = info
	}
	return b
}

// Remove specified property to FooJSONBuilder.
func (b *FooJSONBuilder) Remove(info *FooPropertyInfo) *FooJSONBuilder {
	delete(b._properties, info.fieldName)
	return b
}

// RemoveByJSONNames remove properties to FooJSONBuilder by JSON property name. if name is not in the builder, it will ignore.
func (b *FooJSONBuilder) RemoveByJSONNames(names ...string) *FooJSONBuilder {

	for _, name := range names {
		info := b._jsonPropertyMap[name]
		if info == nil {
			continue
		}
		delete(b._properties, info.fieldName)
	}
	return b
}

// RemoveByNames remove properties to FooJSONBuilder by struct property name. if name is not in the builder, it will ignore.
func (b *FooJSONBuilder) RemoveByNames(names ...string) *FooJSONBuilder {
	for _, name := range names {
		info := b._structPropertyMap[name]
		if info == nil {
			continue
		}
		delete(b._properties, info.fieldName)
	}
	return b
}

// Convert specified non-JSON object to JSON object.
func (b *FooJSONBuilder) Convert(orig *Foo) (*FooJSON, error) {
	if orig == nil {
		return nil, nil
	}
	ret := &FooJSON{}

	for _, info := range b._properties {
		if err := info.Encoder(orig, ret); err != nil {
			return nil, err
		}
	}

	return ret, nil
}

// ConvertList specified non-JSON slice to JSONList.
func (b *FooJSONBuilder) ConvertList(orig []*Foo) (FooJSONList, error) {
	if orig == nil {
		return nil, nil
	}

	list := make(FooJSONList, len(orig))
	for idx, or := range orig {
		json, err := b.Convert(or)
		if err != nil {
			return nil, err
		}
		list[idx] = json
	}

	return list, nil
}

// Convert specified JSON object to non-JSON object.
func (orig *FooJSON) Convert() (*Foo, error) {
	ret := &Foo{}

	b := NewFooJSONBuilder().AddAll()
	for _, info := range b._properties {
		if err := info.Decoder(orig, ret); err != nil {
			return nil, err
		}
	}

	return ret, nil
}

// Convert specified JSONList to non-JSON slice.
func (jsonList FooJSONList) Convert() ([]*Foo, error) {
	orig := ([]*FooJSON)(jsonList)

	list := make([]*Foo, len(orig))
	for idx, or := range orig {
		obj, err := or.Convert()
		if err != nil {
			return nil, err
		}
		list[idx] = obj
	}

	return list, nil
}

// Marshal non-JSON object to JSON string.
func (b *FooJSONBuilder) Marshal(orig *Foo) ([]byte, error) {
	ret, err := b.Convert(orig)
	if err != nil {
		return nil, err
	}
	return json.Marshal(ret)
}

// HogeJSON is jsonized struct for Hoge.
type HogeJSON struct {
	Hoge1 string `json:"hoge1,omitempty"`
}

// HogeJSONList is synonym about []*HogeJSON.
type HogeJSONList []*HogeJSON

// HogePropertyEncoder is property encoder for [1]sJSON.
type HogePropertyEncoder func(src *Hoge, dest *HogeJSON) error

// HogePropertyDecoder is property decoder for [1]sJSON.
type HogePropertyDecoder func(src *HogeJSON, dest *Hoge) error

// HogePropertyInfo stores property information.
type HogePropertyInfo struct {
	fieldName string
	jsonName  string
	Encoder   HogePropertyEncoder
	Decoder   HogePropertyDecoder
}

// FieldName returns struct field name of property.
func (info *HogePropertyInfo) FieldName() string {
	return info.fieldName
}

// JSONName returns json field name of property.
func (info *HogePropertyInfo) JSONName() string {
	return info.jsonName
}

// HogeJSONBuilder convert between Hoge to HogeJSON mutually.
type HogeJSONBuilder struct {
	_properties        map[string]*HogePropertyInfo
	_jsonPropertyMap   map[string]*HogePropertyInfo
	_structPropertyMap map[string]*HogePropertyInfo
	Hoge1              *HogePropertyInfo
}

// NewHogeJSONBuilder make new HogeJSONBuilder.
func NewHogeJSONBuilder() *HogeJSONBuilder {
	jb := &HogeJSONBuilder{
		_properties:        map[string]*HogePropertyInfo{},
		_jsonPropertyMap:   map[string]*HogePropertyInfo{},
		_structPropertyMap: map[string]*HogePropertyInfo{},
		Hoge1: &HogePropertyInfo{
			fieldName: "Hoge1",
			jsonName:  "hoge1",
			Encoder: func(src *Hoge, dest *HogeJSON) error {
				if src == nil {
					return nil
				}
				dest.Hoge1 = src.Hoge1
				return nil
			},
			Decoder: func(src *HogeJSON, dest *Hoge) error {
				if src == nil {
					return nil
				}
				dest.Hoge1 = src.Hoge1
				return nil
			},
		},
	}
	jb._structPropertyMap["Hoge1"] = jb.Hoge1
	jb._jsonPropertyMap["hoge1"] = jb.Hoge1
	return jb
}

// Properties returns all properties on HogeJSONBuilder.
func (b *HogeJSONBuilder) Properties() []*HogePropertyInfo {
	return []*HogePropertyInfo{
		b.Hoge1,
	}
}

// AddAll adds all property to HogeJSONBuilder.
func (b *HogeJSONBuilder) AddAll() *HogeJSONBuilder {
	b._properties["Hoge1"] = b.Hoge1
	return b
}

// Add specified property to HogeJSONBuilder.
func (b *HogeJSONBuilder) Add(info *HogePropertyInfo) *HogeJSONBuilder {
	b._properties[info.fieldName] = info
	return b
}

// AddByJSONNames add properties to HogeJSONBuilder by JSON property name. if name is not in the builder, it will ignore.
func (b *HogeJSONBuilder) AddByJSONNames(names ...string) *HogeJSONBuilder {
	for _, name := range names {
		info := b._jsonPropertyMap[name]
		if info == nil {
			continue
		}
		b._properties[info.fieldName] = info
	}
	return b
}

// AddByNames add properties to HogeJSONBuilder by struct property name. if name is not in the builder, it will ignore.
func (b *HogeJSONBuilder) AddByNames(names ...string) *HogeJSONBuilder {
	for _, name := range names {
		info := b._structPropertyMap[name]
		if info == nil {
			continue
		}
		b._properties[info.fieldName] = info
	}
	return b
}

// Remove specified property to HogeJSONBuilder.
func (b *HogeJSONBuilder) Remove(info *HogePropertyInfo) *HogeJSONBuilder {
	delete(b._properties, info.fieldName)
	return b
}

// RemoveByJSONNames remove properties to HogeJSONBuilder by JSON property name. if name is not in the builder, it will ignore.
func (b *HogeJSONBuilder) RemoveByJSONNames(names ...string) *HogeJSONBuilder {

	for _, name := range names {
		info := b._jsonPropertyMap[name]
		if info == nil {
			continue
		}
		delete(b._properties, info.fieldName)
	}
	return b
}

// RemoveByNames remove properties to HogeJSONBuilder by struct property name. if name is not in the builder, it will ignore.
func (b *HogeJSONBuilder) RemoveByNames(names ...string) *HogeJSONBuilder {
	for _, name := range names {
		info := b._structPropertyMap[name]
		if info == nil {
			continue
		}
		delete(b._properties, info.fieldName)
	}
	return b
}

// Convert specified non-JSON object to JSON object.
func (b *HogeJSONBuilder) Convert(orig *Hoge) (*HogeJSON, error) {
	if orig == nil {
		return nil, nil
	}
	ret := &HogeJSON{}

	for _, info := range b._properties {
		if err := info.Encoder(orig, ret); err != nil {
			return nil, err
		}
	}

	return ret, nil
}

// ConvertList specified non-JSON slice to JSONList.
func (b *HogeJSONBuilder) ConvertList(orig []*Hoge) (HogeJSONList, error) {
	if orig == nil {
		return nil, nil
	}

	list := make(HogeJSONList, len(orig))
	for idx, or := range orig {
		json, err := b.Convert(or)
		if err != nil {
			return nil, err
		}
		list[idx] = json
	}

	return list, nil
}

// Convert specified JSON object to non-JSON object.
func (orig *HogeJSON) Convert() (*Hoge, error) {
	ret := &Hoge{}

	b := NewHogeJSONBuilder().AddAll()
	for _, info := range b._properties {
		if err := info.Decoder(orig, ret); err != nil {
			return nil, err
		}
	}

	return ret, nil
}

// Convert specified JSONList to non-JSON slice.
func (jsonList HogeJSONList) Convert() ([]*Hoge, error) {
	orig := ([]*HogeJSON)(jsonList)

	list := make([]*Hoge, len(orig))
	for idx, or := range orig {
		obj, err := or.Convert()
		if err != nil {
			return nil, err
		}
		list[idx] = obj
	}

	return list, nil
}

// Marshal non-JSON object to JSON string.
func (b *HogeJSONBuilder) Marshal(orig *Hoge) ([]byte, error) {
	ret, err := b.Convert(orig)
	if err != nil {
		return nil, err
	}
	return json.Marshal(ret)
}

// FugaJSON is jsonized struct for Fuga.
type FugaJSON struct {
	Fuga1 string `json:"fuga1,omitempty"`
}

// FugaJSONList is synonym about []*FugaJSON.
type FugaJSONList []*FugaJSON

// FugaPropertyEncoder is property encoder for [1]sJSON.
type FugaPropertyEncoder func(src *Fuga, dest *FugaJSON) error

// FugaPropertyDecoder is property decoder for [1]sJSON.
type FugaPropertyDecoder func(src *FugaJSON, dest *Fuga) error

// FugaPropertyInfo stores property information.
type FugaPropertyInfo struct {
	fieldName string
	jsonName  string
	Encoder   FugaPropertyEncoder
	Decoder   FugaPropertyDecoder
}

// FieldName returns struct field name of property.
func (info *FugaPropertyInfo) FieldName() string {
	return info.fieldName
}

// JSONName returns json field name of property.
func (info *FugaPropertyInfo) JSONName() string {
	return info.jsonName
}

// FugaJSONBuilder convert between Fuga to FugaJSON mutually.
type FugaJSONBuilder struct {
	_properties        map[string]*FugaPropertyInfo
	_jsonPropertyMap   map[string]*FugaPropertyInfo
	_structPropertyMap map[string]*FugaPropertyInfo
	Fuga1              *FugaPropertyInfo
}

// NewFugaJSONBuilder make new FugaJSONBuilder.
func NewFugaJSONBuilder() *FugaJSONBuilder {
	jb := &FugaJSONBuilder{
		_properties:        map[string]*FugaPropertyInfo{},
		_jsonPropertyMap:   map[string]*FugaPropertyInfo{},
		_structPropertyMap: map[string]*FugaPropertyInfo{},
		Fuga1: &FugaPropertyInfo{
			fieldName: "Fuga1",
			jsonName:  "fuga1",
			Encoder: func(src *Fuga, dest *FugaJSON) error {
				if src == nil {
					return nil
				}
				dest.Fuga1 = src.Fuga1
				return nil
			},
			Decoder: func(src *FugaJSON, dest *Fuga) error {
				if src == nil {
					return nil
				}
				dest.Fuga1 = src.Fuga1
				return nil
			},
		},
	}
	jb._structPropertyMap["Fuga1"] = jb.Fuga1
	jb._jsonPropertyMap["fuga1"] = jb.Fuga1
	return jb
}

// Properties returns all properties on FugaJSONBuilder.
func (b *FugaJSONBuilder) Properties() []*FugaPropertyInfo {
	return []*FugaPropertyInfo{
		b.Fuga1,
	}
}

// AddAll adds all property to FugaJSONBuilder.
func (b *FugaJSONBuilder) AddAll() *FugaJSONBuilder {
	b._properties["Fuga1"] = b.Fuga1
	return b
}

// Add specified property to FugaJSONBuilder.
func (b *FugaJSONBuilder) Add(info *FugaPropertyInfo) *FugaJSONBuilder {
	b._properties[info.fieldName] = info
	return b
}

// AddByJSONNames add properties to FugaJSONBuilder by JSON property name. if name is not in the builder, it will ignore.
func (b *FugaJSONBuilder) AddByJSONNames(names ...string) *FugaJSONBuilder {
	for _, name := range names {
		info := b._jsonPropertyMap[name]
		if info == nil {
			continue
		}
		b._properties[info.fieldName] = info
	}
	return b
}

// AddByNames add properties to FugaJSONBuilder by struct property name. if name is not in the builder, it will ignore.
func (b *FugaJSONBuilder) AddByNames(names ...string) *FugaJSONBuilder {
	for _, name := range names {
		info := b._structPropertyMap[name]
		if info == nil {
			continue
		}
		b._properties[info.fieldName] = info
	}
	return b
}

// Remove specified property to FugaJSONBuilder.
func (b *FugaJSONBuilder) Remove(info *FugaPropertyInfo) *FugaJSONBuilder {
	delete(b._properties, info.fieldName)
	return b
}

// RemoveByJSONNames remove properties to FugaJSONBuilder by JSON property name. if name is not in the builder, it will ignore.
func (b *FugaJSONBuilder) RemoveByJSONNames(names ...string) *FugaJSONBuilder {

	for _, name := range names {
		info := b._jsonPropertyMap[name]
		if info == nil {
			continue
		}
		delete(b._properties, info.fieldName)
	}
	return b
}

// RemoveByNames remove properties to FugaJSONBuilder by struct property name. if name is not in the builder, it will ignore.
func (b *FugaJSONBuilder) RemoveByNames(names ...string) *FugaJSONBuilder {
	for _, name := range names {
		info := b._structPropertyMap[name]
		if info == nil {
			continue
		}
		delete(b._properties, info.fieldName)
	}
	return b
}

// Convert specified non-JSON object to JSON object.
func (b *FugaJSONBuilder) Convert(orig *Fuga) (*FugaJSON, error) {
	if orig == nil {
		return nil, nil
	}
	ret := &FugaJSON{}

	for _, info := range b._properties {
		if err := info.Encoder(orig, ret); err != nil {
			return nil, err
		}
	}

	return ret, nil
}

// ConvertList specified non-JSON slice to JSONList.
func (b *FugaJSONBuilder) ConvertList(orig []*Fuga) (FugaJSONList, error) {
	if orig == nil {
		return nil, nil
	}

	list := make(FugaJSONList, len(orig))
	for idx, or := range orig {
		json, err := b.Convert(or)
		if err != nil {
			return nil, err
		}
		list[idx] = json
	}

	return list, nil
}

// Convert specified JSON object to non-JSON object.
func (orig *FugaJSON) Convert() (*Fuga, error) {
	ret := &Fuga{}

	b := NewFugaJSONBuilder().AddAll()
	for _, info := range b._properties {
		if err := info.Decoder(orig, ret); err != nil {
			return nil, err
		}
	}

	return ret, nil
}

// Convert specified JSONList to non-JSON slice.
func (jsonList FugaJSONList) Convert() ([]*Fuga, error) {
	orig := ([]*FugaJSON)(jsonList)

	list := make([]*Fuga, len(orig))
	for idx, or := range orig {
		obj, err := or.Convert()
		if err != nil {
			return nil, err
		}
		list[idx] = obj
	}

	return list, nil
}

// Marshal non-JSON object to JSON string.
func (b *FugaJSONBuilder) Marshal(orig *Fuga) ([]byte, error) {
	ret, err := b.Convert(orig)
	if err != nil {
		return nil, err
	}
	return json.Marshal(ret)
}
