3

I'm trying to write a function which converts a byte array of JSON string to another in accordance with the type parameter of the return value as the following rule:

  • map[string]interface{}: convert to map[string]interface{}
  • []byte: no conversion, return as is
  • struct: convert to the struc

My code is as follow:

func GetJsonData[T any](jsonByteArray []byte) (result *T, err error) {
    var buff T

    switch any(result).(type) { // https://appliedgo.com/blog/a-tip-and-a-trick-when-working-with-generics
    case *[]byte:
        result = &T(jsonByteArray)
    default:
        err = json.Unmarshal(jsonByteArray, &buff)
        result = &buff
    }

    return
}

This code occurs following type error at the point of cast the type of jsonByteArray to T as follows:

cannot convert jsonByteArray (variable of type []byte) to type T

How can I assign the pointer of this []byte type variable to the generic type return value?

0

1 Answer 1

5

Since T is constrained by any, you can’t directly convert. You have to assert that &jsonByteArray is really the same type as *T in that switch case:

func GetJsonData[T any](jsonByteArray []byte) (result *T, err error) {
    var buff T

    switch any(result).(type) {
    case *[]byte:
        result = any(&jsonByteArray).(*T)
    default:
        err = json.Unmarshal(jsonByteArray, &buff)
        result = &buff
    }

    return
}

This makes the compile error go away, however it isn’t particularly good design. If you need to specialize json.Unmarshal for only one type (*[]byte) you are better off changing the call sites instead of using a generic function.

I assume that your goal is to allow callers to get the byte slice as is, instead of unmarshalling. Then at call site you would call the function as

data := GetJsonData[[]byte](jsonByteArray)

This means that at that point you already know that jsonByteArray is a byte slice.

Then, there’s no reason to call the function. You can simply take the address of the argument: data := &jsonByteArray, and use json.Unmarshal everywhere else.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.