You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言如何将二维数组解析为自定义结构体并跳过指定字段

实现方案

你从API拿到的是位置固定的二维数组格式JSON,不是带键名的对象结构,无法直接通过结构体tag做默认映射,通过自定义结构体的UnmarshalJSON方法按索引取值、直接跳过目标字段即可实现需求,同时可以顺带处理时间戳格式转换。

字段位置对应关系

先明确单条数据的索引和字段映射,索引5为需要跳过的字段:

  • 索引0:毫秒级注册时间戳 → RegistrationDate
  • 索引1:姓名 → Name
  • 索引2:地址 → Address
  • 索引3:城市 → City
  • 索引4:州/省 → State
  • 索引5:值为"pass this"的无用字段,直接跳过
  • 索引6:邮编 → Zip
  • 索引7:毫秒级过期时间戳 → ExpirationDate

完整实现代码

package main

import (
	"encoding/json"
	"fmt"
	"time"
)

type Address struct {
	RegistrationDate string `json:"registrationDate"`
	Name             string `json:"name"`
	Address          string `json:"address"`
	City             string `json:"city"`
	State            string `json:"state"`
	Zip              string `json:"zip"`
	ExpirationDate   string `json:"expirationDate"`
}

// UnmarshalJSON 自定义Address的反序列化逻辑
func (a *Address) UnmarshalJSON(data []byte) error {
	// 先将单条数据解析为通用切片,元素顺序和API返回完全一致
	var arr []interface{}
	if err := json.Unmarshal(data, &arr); err != nil {
		return err
	}
	// 校验数组长度避免越界
	if len(arr) != 8 {
		return fmt.Errorf("invalid data length, expected 8 elements, got %d", len(arr))
	}

	// 按索引赋值,跳过索引5的无用字段
	// 处理注册时间戳:JSON数字默认解析为float64,转毫秒时间后格式化
	regTs, ok := arr[0].(float64)
	if !ok {
		return fmt.Errorf("invalid type for registration timestamp")
	}
	a.RegistrationDate = time.UnixMilli(int64(regTs)).Format("2006-01-02") // 可替换为你需要的时间格式

	// 赋值字符串字段
	if a.Name, ok = arr[1].(string); !ok {
		return fmt.Errorf("invalid type for name")
	}
	if a.Address, ok = arr[2].(string); !ok {
		return fmt.Errorf("invalid type for address")
	}
	if a.City, ok = arr[3].(string); !ok {
		return fmt.Errorf("invalid type for city")
	}
	if a.State, ok = arr[4].(string); !ok {
		return fmt.Errorf("invalid type for state")
	}

	// 索引5字段直接跳过,不做任何处理

	if a.Zip, ok = arr[6].(string); !ok {
		return fmt.Errorf("invalid type for zip")
	}

	// 处理过期时间戳
	expTs, ok := arr[7].(float64)
	if !ok {
		return fmt.Errorf("invalid type for expiration timestamp")
	}
	a.ExpirationDate = time.UnixMilli(int64(expTs)).Format("2006-01-02") // 可替换为你需要的时间格式

	return nil
}

func main() {
	// 模拟API返回的原始数据
	raw := `[
[1501545600000,"a","b","c","d","pass this","e",1651363200000],
[1504224000000,"a","b","c","d","pass this","e",1654041600000]
]`
	var res []Address
	if err := json.Unmarshal([]byte(raw), &res); err != nil {
		panic(err)
	}
	// 打印解析结果,不会包含跳过的字段
	for _, addr := range res {
		fmt.Printf("%+v\n", addr)
	}
}

补充说明

  • 如果你不需要把时间戳转为日期格式,只需要存数字字符串,可以把时间处理部分替换为strconv.FormatInt(int64(regTs), 10)即可,无需引入time包。
  • 这种实现完全不依赖索引5的具体值,只要API返回的数组元素位置不变,哪怕该字段后续值发生变化,也不会影响解析结果。
  • 如果对解析性能有要求,可以把[]interface{}替换为[]json.RawMessage,按索引单独反序列化对应字段,减少类型断言的开销。

内容的提问来源于stack exchange,提问作者user15811966

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 17:09:22