Golang中如何解决js.Value转换为map[string]interface{}类型失败的问题

Golang中如何解决js.Value转换为map[string]interface{}类型失败的问题 在我的WASM代码中,我获取了一个js.Value,它是一个JavaScript对象,并且如此处所示,JavaScript对象与Go的map[string]interface{}映射。

在我的代码中,我尝试了以下方法来从返回的对象中获取数据,使用了这段将JSON转换为map[string]interface{}的代码:

	ReadAll = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		// defer ReadAll.Release()
		cursor := this.Get("result")

		if cursor.Truthy() {
			_ = cursor.Get("key")
			value := cursor.Get("value")

			// Decode incoming json
			jsonMap := make(map[string]interface{})
			json.Unmarshal([]byte(value), &jsonMap)

			//	var content []map[string]interface{}
			//	json.Unmarshal([]byte(jsonMap["name"].(string)), &content)

			Window.Call("alert", jsonMap)
			cursor.Call("continue")

		} else {
			Window.Call("alert", "No more records")
		}
		return nil
	})

但是我遇到了错误:

./cursor.go:20:25: 无法将值(类型 js.Value)转换为类型 byte


更多关于Golang中如何解决js.Value转换为map[string]interface{}类型失败的问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

我通过使用 value.Get() 成功实现了,以下是新的代码:

		if cursor.Truthy() {
			key := cursor.Get("key")
			value := cursor.Get("value")

			data := fmt.Sprintf("Name for id %v is %v, Age: %v, Email: %v", key,
				value.Get("name"), value.Get("age"), value.Get("email"))

            // 等效的 JavaScript 代码:
			// alert("Name for id " + cursor.key + " is " + cursor.value.name + ", Age: "
			// + cursor.value.age + ", Email: " + cursor.value.email);

			Window.Call("alert", data)
			cursor.Call("continue")

		} else {
			Window.Call("alert", "No more records")
		}

更多关于Golang中如何解决js.Value转换为map[string]interface{}类型失败的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在WASM中处理js.Valuemap[string]interface{}的转换时,不能直接使用json.Unmarshal,因为js.Value不是[]byte类型。以下是正确的解决方案:

import (
    "encoding/json"
    "syscall/js"
)

func jsValueToMap(value js.Value) (map[string]interface{}, error) {
    // 使用JSON.stringify将JavaScript对象转换为JSON字符串
    jsonStr := js.Global().Get("JSON").Call("stringify", value).String()
    
    // 将JSON字符串解析为Go的map
    result := make(map[string]interface{})
    err := json.Unmarshal([]byte(jsonStr), &result)
    if err != nil {
        return nil, err
    }
    return result, nil
}

// 在你的代码中使用
ReadAll = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
    cursor := this.Get("result")
    
    if cursor.Truthy() {
        value := cursor.Get("value")
        
        // 正确转换js.Value到map
        jsonMap, err := jsValueToMap(value)
        if err != nil {
            js.Global().Call("alert", "解析错误: "+err.Error())
            return nil
        }
        
        js.Global().Call("alert", js.ValueOf(jsonMap))
        cursor.Call("continue")
    } else {
        js.Global().Call("alert", "No more records")
    }
    return nil
})

如果value已经是JSON字符串,可以直接解析:

ReadAll = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
    cursor := this.Get("result")
    
    if cursor.Truthy() {
        value := cursor.Get("value")
        
        // 检查value是否是字符串
        if value.Type() == js.TypeString {
            jsonMap := make(map[string]interface{})
            err := json.Unmarshal([]byte(value.String()), &jsonMap)
            if err != nil {
                js.Global().Call("alert", "JSON解析错误: "+err.Error())
                return nil
            }
            js.Global().Call("alert", js.ValueOf(jsonMap))
        } else {
            // 如果是JavaScript对象,使用JSON.stringify方法
            jsonStr := js.Global().Get("JSON").Call("stringify", value).String()
            jsonMap := make(map[string]interface{})
            err := json.Unmarshal([]byte(jsonStr), &jsonMap)
            if err != nil {
                js.Global().Call("alert", "对象转换错误: "+err.Error())
                return nil
            }
            js.Global().Call("alert", js.ValueOf(jsonMap))
        }
        
        cursor.Call("continue")
    } else {
        js.Global().Call("alert", "No more records")
    }
    return nil
})

对于更复杂的嵌套结构转换,可以使用递归方法:

func jsValueToGo(value js.Value) interface{} {
    switch value.Type() {
    case js.TypeObject:
        // 检查是否为数组
        if js.Global().Get("Array").Call("isArray", value).Bool() {
            length := value.Length()
            arr := make([]interface{}, length)
            for i := 0; i < length; i++ {
                arr[i] = jsValueToGo(value.Index(i))
            }
            return arr
        }
        
        // 处理普通对象
        keys := js.Global().Get("Object").Call("keys", value)
        m := make(map[string]interface{})
        for i := 0; i < keys.Length(); i++ {
            key := keys.Index(i).String()
            m[key] = jsValueToGo(value.Get(key))
        }
        return m
        
    case js.TypeString:
        return value.String()
    case js.TypeNumber:
        return value.Float()
    case js.TypeBoolean:
        return value.Bool()
    case js.TypeNull, js.TypeUndefined:
        return nil
    default:
        return value.String()
    }
}

// 使用示例
ReadAll = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
    cursor := this.Get("result")
    
    if cursor.Truthy() {
        value := cursor.Get("value")
        goMap := jsValueToGo(value).(map[string]interface{})
        
        // 现在goMap可以直接在Go代码中使用
        js.Global().Call("alert", js.ValueOf(goMap))
        cursor.Call("continue")
    }
    return nil
})
回到顶部