
淘宝商品类目体系是电商平台最核心的基础数据结构之一它决定了商品的展示方式、属性规则、搜索推荐逻辑以及发布规范。本文将系统性地介绍淘宝开放平台提供的类目相关 API 接口涵盖类目查询、属性获取、类目树构建等核心能力并提供完整的 Java 代码实现。一、接口体系概览淘宝开放平台提供了多个类目相关接口各司其职共同构成完整的类目数据体系接口名称核心功能适用场景taobao.itemcats.get批量获取商品类目列表构建类目树、全量同步taobao.item.cat.get获取单个类目详情查询特定类目信息taobao.itemprops.get获取类目属性列表商品发布前的属性规则获取taobao.itempropvalues.get获取类目属性值列表获取属性可选值taobao.itemcats.authorize.get获取商家授权类目和品牌天猫商家发布商品前校验关键概念淘宝商品必须挂靠在叶子类目is_parentfalse下发布叶子类目是指没有子类目的最末级类目。二、核心接口详解2.1 taobao.itemcats.get — 批量获取类目列表这是构建完整类目树的核心接口支持通过parent_cid递归获取子类目。请求参数参数名类型必选说明parent_cidNumber条件父类目 ID0表示根节点获取一级类目cidsNumber[]条件类目 ID 列表逗号分隔与 parent_cid 至少传一个fieldsString[]否返回字段默认cid,parent_cid,name,is_parentdatetimeDate否时间戳用于获取增量变更暂无法使用响应字段字段名类型说明cidNumber类目唯一 IDparent_cidNumber父类目 ID0为根类目nameString类目名称is_parentBoolean是否为父类目有子类目则为 truestatusString状态normal正常、deleted删除sort_orderNumber排序值featuresFeature[]类目特性如freeze表示冻结状态2.2 taobao.item.cat.get — 获取单个类目详情用于查询特定类目的详细信息。请求参数参数名类型必选说明cidNumber是类目 ID响应示例{ item_cat_get_response: { item_cat: { cid: 50008163, parent_cid: 16, name: 女装/女士精品, is_parent: true, status: normal, sort_order: 1, features: [ { attr_key: cat_name, attr_value: 女装 } ] }, request_id: 4e9p1x9z8z8z8z8z8z8z8z8z } }2.3 taobao.itemprops.get — 获取类目属性商品发布前必须获取目标类目的属性规则了解哪些字段必填、哪些是枚举值。请求参数参数名类型必选说明cidNumber是叶子类目 IDtypeNumber否1淘宝属性2天猫属性pidNumber否属性 ID指定则只返回该属性fieldsString否返回字段属性类型说明属性类型说明示例关键属性品牌、型号等核心标识品牌Apple型号iPhone 15商品属性标准属性字段材质、颜色、尺寸绑定属性与 SPU 相关的属性产品库绑定属性销售属性影响 SKU 拼接的属性颜色、尺码不同组合生成不同 SKU三、完整 Java 实现3.1 核心客户端封装import okhttp3.*; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.TimeUnit; /** * 淘宝开放平台类目 API Java 客户端 */ public class TaobaoCategoryClient { private static final String GATEWAY_URL https://eco.taobao.com/router/rest; private static final String APP_KEY your_app_key; private static final String APP_SECRET your_app_secret; private final OkHttpClient httpClient; public TaobaoCategoryClient() { this.httpClient new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .build(); } // 签名生成 /** * 生成 HMAC-MD5 签名 */ public String generateSign(MapString, String params) throws Exception { // 1. 过滤空值排除 sign 和 sign_method ListString sortedKeys params.entrySet().stream() .filter(e - e.getValue() ! null !e.getValue().isEmpty()) .filter(e - !e.getKey().equals(sign) !e.getKey().equals(sign_method)) .map(Map.Entry::getKey) .sorted() .toList(); // 2. 拼接字符串AppSecret key1value1 key2value2 ... AppSecret StringBuilder signStr new StringBuilder(APP_SECRET); for (String key : sortedKeys) { signStr.append(key).append(params.get(key)); } signStr.append(APP_SECRET); // 3. HMAC-MD5 加密 Mac mac Mac.getInstance(HmacMD5); SecretKeySpec secretKey new SecretKeySpec( APP_SECRET.getBytes(StandardCharsets.UTF_8), HmacMD5 ); mac.init(secretKey); byte[] bytes mac.doFinal(signStr.toString().getBytes(StandardCharsets.UTF_8)); // 4. 转十六进制大写 StringBuilder hexString new StringBuilder(); for (byte b : bytes) { String hex Integer.toHexString(b 0xFF); if (hex.length() 1) hexString.append(0); hexString.append(hex); } return hexString.toString().toUpperCase(); } // 公共请求方法 /** * 执行 API 请求 */ private JSONObject executeRequest(MapString, String params) throws Exception { // 添加公共参数 params.put(app_key, APP_KEY); params.put(timestamp, new SimpleDateFormat(yyyy-MM-dd HH:mm:ss).format(new Date())); params.put(format, json); params.put(v, 2.0); params.put(sign_method, hmac-md5); // 生成签名 params.put(sign, generateSign(params)); // 构建表单请求 FormBody.Builder formBuilder new FormBody.Builder(); for (Map.EntryString, String entry : params.entrySet()) { formBuilder.add(entry.getKey(), entry.getValue()); } Request request new Request.Builder() .url(GATEWAY_URL) .post(formBuilder.build()) .build(); try (Response response httpClient.newCall(request).execute()) { if (!response.isSuccessful()) { throw new IOException(HTTP 请求失败: response.code()); } return JSON.parseObject(response.body().string()); } } // 类目查询接口 /** * 获取指定父类目下的子类目列表 * * param parentCid 父类目 ID0 表示获取一级类目 * param fields 返回字段 */ public ListCategory getItemCats(Long parentCid, String fields) throws Exception { MapString, String params new HashMap(); params.put(method, taobao.itemcats.get); params.put(parent_cid, String.valueOf(parentCid)); if (fields ! null !fields.isEmpty()) { params.put(fields, fields); } JSONObject response executeRequest(params); // 检查错误 if (response.containsKey(error_response)) { JSONObject error response.getJSONObject(error_response); throw new RuntimeException( API错误: [ error.getString(code) ] error.getString(msg) ); } // 解析类目列表 JSONObject itemcatsResponse response.getJSONObject(itemcats_get_response); JSONArray itemCats itemcatsResponse.getJSONArray(item_cats); ListCategory categories new ArrayList(); if (itemCats ! null) { for (int i 0; i itemCats.size(); i) { JSONObject cat itemCats.getJSONObject(i); categories.add(parseCategory(cat)); } } return categories; } /** * 获取单个类目详情 */ public Category getItemCat(Long cid) throws Exception { MapString, String params new HashMap(); params.put(method, taobao.item.cat.get); params.put(cid, String.valueOf(cid)); JSONObject response executeRequest(params); if (response.containsKey(error_response)) { JSONObject error response.getJSONObject(error_response); throw new RuntimeException( API错误: [ error.getString(code) ] error.getString(msg) ); } JSONObject catResponse response.getJSONObject(item_cat_get_response); JSONObject itemCat catResponse.getJSONObject(item_cat); return parseCategory(itemCat); } /** * 获取类目属性列表 */ public ListItemProp getItemProps(Long cid, Long type) throws Exception { MapString, String params new HashMap(); params.put(method, taobao.itemprops.get); params.put(cid, String.valueOf(cid)); if (type ! null) { params.put(type, String.valueOf(type)); // 1淘宝, 2天猫 } JSONObject response executeRequest(params); if (response.containsKey(error_response)) { JSONObject error response.getJSONObject(error_response); throw new RuntimeException( API错误: [ error.getString(code) ] error.getString(msg) ); } JSONObject propsResponse response.getJSONObject(itemprops_get_response); JSONArray itemProps propsResponse.getJSONArray(item_props); ListItemProp props new ArrayList(); if (itemProps ! null) { for (int i 0; i itemProps.size(); i) { JSONObject prop itemProps.getJSONObject(i); props.add(parseItemProp(prop)); } } return props; } // 数据解析 private Category parseCategory(JSONObject json) { Category category new Category(); category.setCid(json.getLong(cid)); category.setParentCid(json.getLong(parent_cid)); category.setName(json.getString(name)); category.setParent(json.getBooleanValue(is_parent)); category.setStatus(json.getString(status)); category.setSortOrder(json.getIntValue(sort_order)); // 解析 features JSONArray features json.getJSONArray(features); if (features ! null) { MapString, String featureMap new HashMap(); for (int i 0; i features.size(); i) { JSONObject f features.getJSONObject(i); featureMap.put(f.getString(attr_key), f.getString(attr_value)); } category.setFeatures(featureMap); } return category; } private ItemProp parseItemProp(JSONObject json) { ItemProp prop new ItemProp(); prop.setPid(json.getLong(pid)); prop.setName(json.getString(name)); prop.setIsKeyProp(json.getBooleanValue(is_key_prop)); prop.setIsSaleProp(json.getBooleanValue(is_sale_prop)); prop.setIsColorProp(json.getBooleanValue(is_color_prop)); prop.setIsEnumProp(json.getBooleanValue(is_enum_prop)); prop.setIsInputProp(json.getBooleanValue(is_input_prop)); prop.setIsItemProp(json.getBooleanValue(is_item_prop)); prop.setMust(json.getBooleanValue(must)); prop.setMulti(json.getBooleanValue(multi)); prop.setStatus(json.getString(status)); prop.setSortOrder(json.getIntValue(sort_order)); // 解析属性值 JSONArray propValues json.getJSONArray(prop_values); if (propValues ! null) { ListPropValue values new ArrayList(); for (int i 0; i propValues.size(); i) { JSONObject v propValues.getJSONObject(i); PropValue pv new PropValue(); pv.setVid(v.getLong(vid)); pv.setName(v.getString(name)); pv.setNameAlias(v.getString(name_alias)); pv.setStatus(v.getString(status)); pv.setSortOrder(v.getIntValue(sort_order)); values.add(pv); } prop.setPropValues(values); } return prop; } // 数据模型 public static class Category { private Long cid; private Long parentCid; private String name; private boolean isParent; private String status; private int sortOrder; private MapString, String features; // Getters Setters public Long getCid() { return cid; } public void setCid(Long cid) { this.cid cid; } public Long getParentCid() { return parentCid; } public void setParentCid(Long parentCid) { this.parentCid parentCid; } public String getName() { return name; } public void setName(String name) { this.name name; } public boolean isParent() { return isParent; } public void setParent(boolean parent) { isParent parent; } public String getStatus() { return status; } public void setStatus(String status) { this.status status; } public int getSortOrder() { return sortOrder; } public void setSortOrder(int sortOrder) { this.sortOrder sortOrder; } public MapString, String getFeatures() { return features; } public void setFeatures(MapString, String features) { this.features features; } Override public String toString() { return String.format(Category{cid%d, name%s, parentCid%d, isParent%s}, cid, name, parentCid, isParent); } } public static class ItemProp { private Long pid; private String name; private boolean isKeyProp; // 是否关键属性 private boolean isSaleProp; // 是否销售属性 private boolean isColorProp; // 是否颜色属性 private boolean isEnumProp; // 是否枚举属性 private boolean isInputProp; // 是否可输入属性 private boolean isItemProp; // 是否商品属性 private boolean must; // 是否必填 private boolean multi; // 是否多选 private String status; private int sortOrder; private ListPropValue propValues; // Getters Setters public Long getPid() { return pid; } public void setPid(Long pid) { this.pid pid; } public String getName() { return name; } public void setName(String name) { this.name name; } public boolean isKeyProp() { return isKeyProp; } public void setIsKeyProp(boolean keyProp) { isKeyProp keyProp; } public boolean isSaleProp() { return isSaleProp; } public void setIsSaleProp(boolean saleProp) { isSaleProp saleProp; } public boolean isColorProp() { return isColorProp; } public void setIsColorProp(boolean colorProp) { isColorProp colorProp; } public boolean isEnumProp() { return isEnumProp; } public void setIsEnumProp(boolean enumProp) { isEnumProp enumProp; } public boolean isInputProp() { return isInputProp; } public void setIsInputProp(boolean inputProp) { isInputProp inputProp; } public boolean isItemProp() { return isItemProp; } public void setIsItemProp(boolean itemProp) { isItemProp itemProp; } public boolean isMust() { return must; } public void setMust(boolean must) { this.must must; } public boolean isMulti() { return multi; } public void setMulti(boolean multi) { this.multi multi; } public String getStatus() { return status; } public void setStatus(String status) { this.status status; } public int getSortOrder() { return sortOrder; } public void setSortOrder(int sortOrder) { this.sortOrder sortOrder; } public ListPropValue getPropValues() { return propValues; } public void setPropValues(ListPropValue propValues) { this.propValues propValues; } } public static class PropValue { private Long vid; private String name; private String nameAlias; private String status; private int sortOrder; // Getters Setters public Long getVid() { return vid; } public void setVid(Long vid) { this.vid vid; } public String getName() { return name; } public void setName(String name) { this.name name; } public String getNameAlias() { return nameAlias; } public void setNameAlias(String nameAlias) { this.nameAlias nameAlias; } public String getStatus() { return status; } public void setStatus(String status) { this.status status; } public int getSortOrder() { return sortOrder; } public void setSortOrder(int sortOrder) { this.sortOrder sortOrder; } } }四、递归构建完整类目树import java.util.*; /** * 类目树构建器 */ public class CategoryTreeBuilder { private final TaobaoCategoryClient client; public CategoryTreeBuilder(TaobaoCategoryClient client) { this.client client; } /** * 递归构建完整类目树 */ public CategoryNode buildCategoryTree() throws Exception { CategoryNode root new CategoryNode(0L, 根类目, 0); buildChildren(root); return root; } private void buildChildren(CategoryNode parentNode) throws Exception { ListTaobaoCategoryClient.Category children client.getItemCats(parentNode.getCid(), cid,parent_cid,name,is_parent,status,sort_order); for (TaobaoCategoryClient.Category cat : children) { CategoryNode childNode new CategoryNode( cat.getCid(), cat.getName(), parentNode.getLevel() 1 ); childNode.setParentCid(cat.getParentCid()); childNode.setStatus(cat.getStatus()); childNode.setSortOrder(cat.getSortOrder()); childNode.setLeaf(!cat.isParent()); parentNode.addChild(childNode); // 递归获取子类目 if (cat.isParent()) { buildChildren(childNode); } } } /** * 查找叶子类目 */ public ListCategoryNode findLeafNodes(CategoryNode root) { ListCategoryNode leaves new ArrayList(); collectLeaves(root, leaves); return leaves; } private void collectLeaves(CategoryNode node, ListCategoryNode leaves) { if (node.isLeaf()) { leaves.add(node); return; } for (CategoryNode child : node.getChildren()) { collectLeaves(child, leaves); } } /** * 根据 CID 查找类目节点 */ public CategoryNode findByCid(CategoryNode root, Long cid) { if (root.getCid().equals(cid)) return root; for (CategoryNode child : root.getChildren()) { CategoryNode found findByCid(child, cid); if (found ! null) return found; } return null; } // 类目树节点模型 public static class CategoryNode { private Long cid; private String name; private Long parentCid; private int level; private String status; private int sortOrder; private boolean isLeaf; private ListCategoryNode children new ArrayList(); public CategoryNode(Long cid, String name, int level) { this.cid cid; this.name name; this.level level; } public void addChild(CategoryNode child) { children.add(child); } // Getters Setters public Long getCid() { return cid; } public void setCid(Long cid) { this.cid cid; } public String getName() { return name; } public void setName(String name) { this.name name; } public Long getParentCid() { return parentCid; } public void setParentCid(Long parentCid) { this.parentCid parentCid; } public int getLevel() { return level; } public void setLevel(int level) { this.level level; } public String getStatus() { return status; } public void setStatus(String status) { this.status status; } public int getSortOrder() { return sortOrder; } public void setSortOrder(int sortOrder) { this.sortOrder sortOrder; } public boolean isLeaf() { return isLeaf; } public void setLeaf(boolean leaf) { isLeaf leaf; } public ListCategoryNode getChildren() { return children; } public void setChildren(ListCategoryNode children) { this.children children; } Override public String toString() { StringBuilder sb new StringBuilder(); for (int i 0; i level; i) sb.append( ); sb.append(String.format([%d] %s (cid%d, leaf%s), level, name, cid, isLeaf)); return sb.toString(); } } // 使用示例 public static void main(String[] args) { try { TaobaoCategoryClient client new TaobaoCategoryClient(); CategoryTreeBuilder builder new CategoryTreeBuilder(client); // 构建完整类目树 System.out.println(正在构建类目树...); CategoryNode root builder.buildCategoryTree(); // 打印类目树前三级 printTree(root, 3); // 统计叶子类目数量 ListCategoryNode leaves builder.findLeafNodes(root); System.out.println(\n叶子类目总数: leaves.size()); // 查找特定类目 CategoryNode dressNode builder.findByCid(root, 50008163L); if (dressNode ! null) { System.out.println(\n找到类目: dressNode.getName()); System.out.println(层级: dressNode.getLevel()); System.out.println(是否叶子: dressNode.isLeaf()); } } catch (Exception e) { e.printStackTrace(); } } private static void printTree(CategoryNode node, int maxLevel) { if (node.getLevel() maxLevel) return; System.out.println(node); for (CategoryNode child : node.getChildren()) { printTree(child, maxLevel); } } }五、商品发布前的类目属性校验/** * 商品发布前的类目属性校验工具 */ public class CategoryPublishValidator { private final TaobaoCategoryClient client; public CategoryPublishValidator(TaobaoCategoryClient client) { this.client client; } /** * 校验类目是否可以发布商品 */ public PublishValidationResult validateCategoryForPublish(Long cid, boolean isTmall) throws Exception { PublishValidationResult result new PublishValidationResult(); // 1. 获取类目详情 TaobaoCategoryClient.Category category client.getItemCat(cid); result.setCategory(category); // 2. 检查是否为叶子类目 if (category.isParent()) { result.addError(类目不是叶子类目商品必须挂靠在叶子类目下); return result; } // 3. 检查类目状态 if (!normal.equals(category.getStatus())) { result.addError(类目状态异常: category.getStatus()); return result; } // 4. 获取类目属性 Long type isTmall ? 2L : 1L; ListTaobaoCategoryClient.ItemProp props client.getItemProps(cid, type); result.setProperties(props); // 5. 分析必填属性 ListTaobaoCategoryClient.ItemProp requiredProps props.stream() .filter(TaobaoCategoryClient.ItemProp::isMust) .toList(); result.setRequiredProperties(requiredProps); // 6. 分析销售属性影响 SKU ListTaobaoCategoryClient.ItemProp saleProps props.stream() .filter(TaobaoCategoryClient.ItemProp::isSaleProp) .toList(); result.setSaleProperties(saleProps); result.setValid(result.getErrors().isEmpty()); return result; } public static class PublishValidationResult { private boolean valid; private TaobaoCategoryClient.Category category; private ListTaobaoCategoryClient.ItemProp properties; private ListTaobaoCategoryClient.ItemProp requiredProperties; private ListTaobaoCategoryClient.ItemProp saleProperties; private ListString errors new ArrayList(); public void addError(String error) { errors.add(error); valid false; } // Getters Setters public boolean isValid() { return valid; } public void setValid(boolean valid) { this.valid valid; } public TaobaoCategoryClient.Category getCategory() { return category; } public void setCategory(TaobaoCategoryClient.Category category) { this.category category; } public ListTaobaoCategoryClient.ItemProp getProperties() { return properties; } public void setProperties(ListTaobaoCategoryClient.ItemProp properties) { this.properties properties; } public ListTaobaoCategoryClient.ItemProp getRequiredProperties() { return requiredProperties; } public void setRequiredProperties(ListTaobaoCategoryClient.ItemProp requiredProperties) { this.requiredProperties requiredProperties; } public ListTaobaoCategoryClient.ItemProp getSaleProperties() { return saleProperties; } public void setSaleProperties(ListTaobaoCategoryClient.ItemProp saleProperties) { this.saleProperties saleProperties; } public ListString getErrors() { return errors; } public void setErrors(ListString errors) { this.errors errors; } } }六、Maven 依赖dependencies !-- OkHttp HTTP 客户端 -- dependency groupIdcom.squareup.okhttp3/groupId artifactIdokhttp/artifactId version4.12.0/version /dependency !-- FastJSON JSON 解析 -- dependency groupIdcom.alibaba/groupId artifactIdfastjson/artifactId version2.0.25/version /dependency !-- 日志 -- dependency groupIdorg.slf4j/groupId artifactIdslf4j-simple/artifactId version2.0.7/version /dependency /dependencies七、常见错误码错误码错误信息解决方案40Invalid arguments检查必填参数是否完整cid 是否为数字40001Insufficient isv permissions应用无权限调用该接口需在开放平台申请40002Invalid timestamp时间戳格式错误或与服务端时间偏差超过 10 分钟40003Invalid signature签名生成错误检查 HMAC-MD5 算法和参数排序40004Invalid method接口名称拼写错误40006Invalid app_keyApp Key 不存在或已失效50001API call limit exceeded调用频率超限降低调用频率或申请提升额度isv.invalid-parameter:cidcid 参数不合法传入的类目 ID 不存在或已删除八、最佳实践建议缓存策略类目数据变化频率低建议本地缓存 24-48 小时减少 API 调用增量更新定期同步类目变更关注statusdeleted的类目叶子类目校验发布商品前务必校验目标类目是否为叶子类目属性缓存类目属性数据量大建议按类目分别缓存错误重试网络异常时实现指数退避重试权限管理天猫商家需额外调用itemcats.authorize.get校验授权类目如遇任何疑问或有进一步的需求请随时与我私信或者评论联系。