为何OroCommerce订单创建POST请求未传递关联数据属性?
Angular2-JsonApi 与 OroCommerce API 对接:创建Order时关联字段未出现在请求中的解决方案
在使用angular2-jsonapi对接OroCommerce API创建Order对象时,POST请求返回400错误,billingAddress、shippingAddress和lineItems字段未出现在请求Payload中,触发非空约束和数量约束错误。以下是问题原因分析及解决方案:
问题原因
- LineItems类型不匹配:Order模型中
@HasMany()装饰的lineItems被定义为单个OrderLineItem对象,但HasMany关联对应集合类型,应为数组OrderLineItem[],导致无法正确序列化数组数据。 - 未保存关联对象未被序列化:
billingAddress和shippingAddress是新创建的OrderAddress实例(无服务器分配的ID),angular2-jsonapi默认不会自动将未保存的关联对象包含到主对象的创建请求中。 - PaymentMethod格式错误:Order模型中
paymentMethod定义为数组类型,但创建时传入的是单个对象,可能引发序列化异常。
解决方案
1. 修复Order模型的类型定义
修改Order模型中的lineItems和paymentMethod类型,确保与关联类型和数据格式匹配:
@JsonApiModelConfig({ type: 'orders', }) export class Order extends JsonApiModel { // ... 其他属性保持不变 @Attribute() public paymentMethod: { code: string, label: string }[]; // 明确数组类型 @BelongsTo() public billingAddress: OrderAddress; @BelongsTo() public shippingAddress: OrderAddress; // ... 其他关联属性 @HasMany() public lineItems: OrderLineItem[]; // HasMany关联对应数组类型 }
2. 处理未保存的关联对象
针对新创建的地址和订单项,有两种可行方案:
方案A:先保存关联对象,再关联到Order
先将OrderAddress和OrderLineItem保存到服务器,获取合法ID后再关联到Order对象,确保请求中包含有效的关联引用:
import { switchMap } from 'rxjs/operators'; public createOrder(): Observable<Order> { const orderAddress = new OrderAddress(this.datastore, { city: 'Grenoble', firstName: 'John', lastName: 'Doe', organization: 'MyOrg', postalCode: '38000', street: '123 main street', country: 'FR', region: 'Isère', }); const lineItem = new OrderLineItem(this.datastore, { quantity: '1', productUnit: 'each', }); // 按顺序保存关联对象,再创建Order return orderAddress.save().pipe( switchMap(savedAddress => lineItem.save().pipe( switchMap(savedLineItem => { const newOrder = this.datastore.createRecord(Order, { owner: '1', customer: '34', customerUser: '34', currency: 'EUR', paymentStatus: { code: PaymentStatusCodes.pending, label: 'lab1' }, paymentMethod: [{ // 改为数组格式 code: 'payment_term_1', label: 'payment_term_1' }], lineItems: [savedLineItem], billingAddress: savedAddress, shippingAddress: savedAddress, }); return newOrder.save(); }) )), catchError(errorResponse => { if (errorResponse instanceof ErrorResponse) { return throwError(errorResponse.errors[0]); } return throwError(this.errorService.getRelevantMessage(errorResponse)); }) ); }
方案B:配置关联装饰器序列化嵌套对象(仅当OroCommerce API支持嵌套创建时)
如果OroCommerce API允许在创建Order的同时创建关联的地址和订单项,可修改模型的关联装饰器,指定序列化方式为included,让angular2-jsonapi将关联对象包含在请求的included部分:
// 修改Order模型中的关联装饰器 @BelongsTo({ serialize: 'included' }) public billingAddress: OrderAddress; @BelongsTo({ serialize: 'included' }) public shippingAddress: OrderAddress; @HasMany({ serialize: 'included' }) public lineItems: OrderLineItem[];
此方案无需提前保存关联对象,直接传入新创建的实例即可。
验证修改
- 检查浏览器请求Payload,确认
billingAddress、shippingAddress和lineItems已出现在relationships或included部分 - 确认
paymentMethod为数组格式,与模型定义一致
内容的提问来源于stack exchange,提问作者Emile Haas
相关产品推荐
相关产品推荐

