gofr-dev/gofr · error

failed to unmarshal JSON: %w

Error message

failed to unmarshal JSON: %w

What it means

FromJSON decodes a JSON string into dest for use with KVStore.Get. This error wraps json.Unmarshal failures with 'failed to unmarshal JSON: %w' when the stored string is invalid JSON or incompatible with dest's shape.

Source

Thrown at pkg/gofr/datasource/kv-store/dynamodb/dynamo.go:135

	if tracer, ok := tracer.(trace.Tracer); ok {
		c.tracer = tracer
	}
}

// ToJSON converts a Go struct to JSON string for use with KVStore.Set.
func ToJSON(value any) (string, error) {
	jsonData, err := json.Marshal(value)
	if err != nil {
		return "", fmt.Errorf("failed to marshal value to JSON: %w", err)
	}

	return string(jsonData), nil
}

// FromJSON converts a JSON string to a Go struct for use with KVStore.Get.
func FromJSON(jsonData string, dest any) error {
	if err := json.Unmarshal([]byte(jsonData), dest); err != nil {
		return fmt.Errorf("failed to unmarshal JSON: %w", err)
	}

	return nil
}

func (c *Client) Get(ctx context.Context, key string) (string, error) {
	if !c.connected {
		return "", errClientNotConnected
	}

	span := c.addTrace(ctx, "get", key)
	defer c.sendOperationsStats(time.Now(), "GET", "get", span, key)

	input := &dynamodb.GetItemInput{
		TableName: aws.String(c.configs.Table),
		Key: map[string]types.AttributeValue{
			c.configs.PartitionKeyName: &types.AttributeValueMemberS{Value: key},
		},

View on GitHub (pinned to 187eb24962)

Solutions

  1. Always write with ToJSON so stored values are valid JSON
  2. Pass a dest whose fields match the stored JSON types; check the wrapped err for a *json.UnmarshalTypeError detail
  3. Handle legacy/plain-string values: attempt FromJSON and fall back to raw string handling
  4. Validate the stored value is non-empty before unmarshaling

Example fix

// before
var u User
err := FromJSON(raw, &u) // fails on plain text
// after
var u User
if err := FromJSON(raw, &u); err != nil {
    u = User{Name: raw} // fallback for legacy raw values
}
Defensive patterns

Strategy: validation

Validate before calling

func validJSON(s string) error {
    if s == "" { return errors.New("empty JSON") }
    if !json.Valid([]byte(s)) { return errors.New("invalid JSON payload") }
    return nil
}
// call before FromJSON: if err := validJSON(raw); err != nil { handle }

Type guard

func canUnmarshal[T any](s string) bool { var v T; return json.Unmarshal([]byte(s), &v) == nil }

Try / catch

var dest MyStruct
if err := dynamodb.FromJSON(raw, &dest); err != nil {
    var te *json.UnmarshalTypeError
    if errors.As(err, &te) { log.Printf("type mismatch at %v", te.Field) }
    return fallbackDecode(raw)
}

Prevention

When it happens

Trigger: Calling FromJSON on a value that was Set as a raw string rather than via ToJSON; dest type not matching stored JSON (e.g. number into string field); empty or truncated stored value; malformed JSON written by another writer.

Common situations: Mixed writers to the same KV store (one uses ToJSON, one stores plain text), schema drift after struct field renames/type changes, reading keys written by an older app version.

Related errors


AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01). Data as JSON: /api/errors/bfca487157279244. Report an issue: GitHub.