pkg/common/util/response.go (149 lines of code) (raw):

/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package util import ( "encoding/json" "fmt" "reflect" "strings" ) import ( "github.com/apache/dubbo-go-pixiu/pkg/client" ) func NewDubboResponse(data any, hump bool) *client.UnaryResponse { r, _ := dealResp(data, hump) bytes, _ := json.Marshal(r) return &client.UnaryResponse{Data: bytes} } func dealResp(in any, HumpToLine bool) (any, error) { if in == nil { return in, nil } switch reflect.TypeOf(in).Kind() { case reflect.Map: if _, ok := in.(map[any]any); ok { m := mapIItoMapSI(in) if HumpToLine { m = humpToLine(m) } return m, nil } else if inm, ok := in.(map[string]any); ok { if HumpToLine { m := humpToLine(in) return m, nil } return inm, nil } case reflect.Slice: if data, ok := in.([]byte); ok { // raw bytes data should return directly return data, nil } value := reflect.ValueOf(in) newTemps := make([]any, 0, value.Len()) for i := 0; i < value.Len(); i++ { if value.Index(i).CanInterface() { newTemp, e := dealResp(value.Index(i).Interface(), HumpToLine) if e != nil { return nil, e } newTemps = append(newTemps, newTemp) } else { return nil, fmt.Errorf("unexpect err,value:%v", value) } } return newTemps, nil default: return in, nil } return in, nil } func mapIItoMapSI(in any) any { var inMap map[any]any if v, ok := in.(map[any]any); !ok { return in } else { inMap = v } outMap := make(map[string]any, len(inMap)) for k, v := range inMap { if v == nil { continue } s := fmt.Sprint(k) if s == "class" { // ignore the "class" field continue } vt := reflect.TypeOf(v) switch vt.Kind() { case reflect.Map: if _, ok := v.(map[any]any); ok { v = mapIItoMapSI(v) } case reflect.Slice: vl := reflect.ValueOf(v) os := make([]any, 0, vl.Len()) for i := 0; i < vl.Len(); i++ { if vl.Index(i).CanInterface() { osv := mapIItoMapSI(vl.Index(i).Interface()) os = append(os, osv) } } v = os } outMap[s] = v } return outMap } // traverse all the keys in the map and change the hump to underline func humpToLine(in any) any { var m map[string]any if v, ok := in.(map[string]any); ok { m = v } else { return in } out := make(map[string]any, len(m)) for k1, v1 := range m { x := humpToUnderline(k1) if v1 == nil { out[x] = v1 } else if reflect.TypeOf(v1).Kind() == reflect.Struct { out[x] = humpToLine(struct2Map(v1)) } else if reflect.TypeOf(v1).Kind() == reflect.Slice { value := reflect.ValueOf(v1) newTemps := make([]any, 0, value.Len()) for i := 0; i < value.Len(); i++ { newTemp := humpToLine(value.Index(i).Interface()) newTemps = append(newTemps, newTemp) } out[x] = newTemps } else if reflect.TypeOf(v1).Kind() == reflect.Map { out[x] = humpToLine(v1) } else { out[x] = v1 } } return out } func humpToUnderline(s string) string { data := make([]byte, 0, len(s)*2) j := false num := len(s) for i := 0; i < num; i++ { d := s[i] if i > 0 && d >= 'A' && d <= 'Z' && j { data = append(data, '_') } if d != '_' { j = true } data = append(data, d) } return strings.ToLower(string(data[:])) } func struct2Map(obj any) map[string]any { t := reflect.TypeOf(obj) v := reflect.ValueOf(obj) data := make(map[string]any) for i := 0; i < t.NumField(); i++ { data[t.Field(i).Name] = v.Field(i).Interface() } return data }