func (n *NameProvider) GetJSONNames(subject interface{}) []string {
	n.lock.Lock()
	defer n.lock.Unlock()
	tpe := reflect.Indirect(reflect.ValueOf(subject)).Type()
	names, ok := n.index[tpe]
	if !ok {
		names = n.makeNameIndex(tpe)
	}
	var res []string
	for k := range names.jsonNames {
		res = append(res, k)
	}
	return res
}
GetJSONNames gets all the json property names for a type
package swag
import (
	"bytes"
	"encoding/json"
	"log"
	"reflect"
	"strings"
	"sync"
	"github.com/mailru/easyjson/jlexer"
	"github.com/mailru/easyjson/jwriter"
)
var nullJSON = []byte("null")
var DefaultJSONNameProvider = NewNameProvider()
const comma = byte(',')
var closers = map[byte]byte{
	'{': '}',
	'[': ']',
}
type ejMarshaler interface {
	MarshalEasyJSON(w *jwriter.Writer)
}
type ejUnmarshaler interface {
	UnmarshalEasyJSON(w *jlexer.Lexer)
}
func WriteJSON(data interface{}) ([]byte, error) {
	if d, ok := data.(ejMarshaler); ok {
		jw := new(jwriter.Writer)
		d.MarshalEasyJSON(jw)
		return jw.BuildBytes()
	}
	if d, ok := data.(json.Marshaler); ok {
		return d.MarshalJSON()
	}
	return json.Marshal(data)
}
func ReadJSON(data []byte, value interface{}) error {
	if d, ok := value.(ejUnmarshaler); ok {
		jl := &jlexer.Lexer{Data: data}
		d.UnmarshalEasyJSON(jl)
		return jl.Error()
	}
	if d, ok := value.(json.Unmarshaler); ok {
		return d.UnmarshalJSON(data)
	}
	return json.Unmarshal(data, value)
}
func DynamicJSONToStruct(data interface{}, target interface{}) error {
	b, err := WriteJSON(data)
	if err != nil {
		return err
	}
	if err := ReadJSON(b, target); err != nil {
		return err
	}
	return nil
}
func ConcatJSON(blobs ...[]byte) []byte {
	if len(blobs) == 0 {
		return nil
	}
	last := len(blobs) - 1
	for blobs[last] == nil || bytes.Equal(blobs[last], nullJSON) {
		last = last - 1
		if last < 0 {
			return nil
		}
	}
	if last == 0 {
		return blobs[0]
	}
	var opening, closing byte
	var idx, a int
	buf := bytes.NewBuffer(nil)
	for i, b := range blobs[:last+1] {
		if b == nil || bytes.Equal(b, nullJSON) {
			continue
		}
		if len(b) > 0 && opening == 0 {  
			opening, closing = b[0], closers[b[0]]
		}
		if opening != '{' && opening != '[' {
			continue  
		}
		if len(b) < 3 {  
			if i == last && a > 0 {
				if err := buf.WriteByte(closing); err != nil {
					log.Println(err)
				}
			}
			continue
		}
		idx = 0
		if a > 0 {  
			if err := buf.WriteByte(comma); err != nil {
				log.Println(err)
			}
			idx = 1  
		}
		if i != last {  
			if _, err := buf.Write(b[idx : len(b)-1]); err != nil {
				log.Println(err)
			}
		} else {  
			if _, err := buf.Write(b[idx:]); err != nil {
				log.Println(err)
			}
		}
		a++
	}
	if buf.Len() == 0 {
		if err := buf.WriteByte(opening); err != nil {
			log.Println(err)
		}
		if err := buf.WriteByte(closing); err != nil {
			log.Println(err)
		}
	}
	return buf.Bytes()
}
func ToDynamicJSON(data interface{}) interface{} {
	b, err := json.Marshal(data)
	if err != nil {
		log.Println(err)
	}
	var res interface{}
	if err := json.Unmarshal(b, &res); err != nil {
		log.Println(err)
	}
	return res
}
func FromDynamicJSON(data, target interface{}) error {
	b, err := json.Marshal(data)
	if err != nil {
		log.Println(err)
	}
	return json.Unmarshal(b, target)
}
type NameProvider struct {
	lock  *sync.Mutex
	index map[reflect.Type]nameIndex
}
type nameIndex struct {
	jsonNames map[string]string
	goNames   map[string]string
}
func NewNameProvider() *NameProvider {
	return &NameProvider{
		lock:  &sync.Mutex{},
		index: make(map[reflect.Type]nameIndex),
	}
}
func buildnameIndex(tpe reflect.Type, idx, reverseIdx map[string]string) {
	for i := 0; i < tpe.NumField(); i++ {
		targetDes := tpe.Field(i)
		if targetDes.PkgPath != "" {  
			continue
		}
		if targetDes.Anonymous {  
			buildnameIndex(targetDes.Type, idx, reverseIdx)
			continue
		}
		if tag := targetDes.Tag.Get("json"); tag != "" {
			parts := strings.Split(tag, ",")
			if len(parts) == 0 {
				continue
			}
			nm := parts[0]
			if nm == "-" {
				continue
			}
			if nm == "" {  
				nm = targetDes.Name
			}
			idx[nm] = targetDes.Name
			reverseIdx[targetDes.Name] = nm
		}
	}
}
func newNameIndex(tpe reflect.Type) nameIndex {
	var idx = make(map[string]string, tpe.NumField())
	var reverseIdx = make(map[string]string, tpe.NumField())
	buildnameIndex(tpe, idx, reverseIdx)
	return nameIndex{jsonNames: idx, goNames: reverseIdx}
}