打算Avobject里面存一个List, list是Pointer类型的,也就是其他表的class。
无论是 avobject.put、addAll 都是报106错误。

但是如果add,则看到结果是
[
目标list
]

也就是list无缘无故被塞进了一个数组。

用 addAll 或者 addAllUnique,注意参数的类型是 java.util.Collection<?>。我怀疑是参数类型不对,因为 add 没报错 106(add 的类型是 Object)。

感谢回复。

尝试过addAll或者addAllUnique用的是List、ArrayList、LinkedList都是106,
也尝试过for循环来遍历 add 的方案, 也是106。

诡异。方便贴下会触发 106 的示例代码么?

// Travel 是按照文档写的AvObject实现的子类化,如果直接用AvObject,结果还是106错误 
Travel travel = new Travel();
travel.putDate("");
travel.putRemark(remark);
travel.putStartCity(startLocation);
travel.putTargetCity(targetLocation);
travel.putUserId(AVUser.getCurrentUser().getObjectId());

ArrayList<Form> formsList = createFormsList(tagMap);

// 方案一,遍历List存进数组,106错误
Form[] forms = new Form[formsList.size()];
for (int i = 0; i < formsList.size(); i++) {
       forms[i] = formsList.get(i);
       //  travel.add("forms", forms[i]);
       //  travel.add("forms", AVObject.createWithoutData(Form.class, forms[i].getObjectId()));
}

// 方案二,直接将List怼进Avobject, 但是后端数据多了一层数组包裹
// travel.add("forms", forms);

// 方案三,直接按照文档调用 addAll, 106错误
//  travel.addAll("forms", formsList);
//   travel.addAllUnique("forms", formsList);

// 保存到服务端
travel.saveInBackground();

private ArrayList<Form> createFormsList(Map<String, String> tagMap) {
    ArrayList<Form> forms = Lists.newArrayList();

    // 根据一个数据来源Map来遍历构建Form,Form也是AvObject的子类化
    for (...) {
         Form form = new Form();
         form.putTypeName(typeName);
         form.putContent(formContent);
         form.putUserId(AVUser.getCurrentUser().getObjectId());
         form.putFormTypeId(formType.getObjectId());
         forms.add(form);
    }
    return forms;
}

方便贴一下这些信息么?

  1. 开启调试日志后,触发 106 的详细错误信息。
  2. Form 类的定义。

@AVClassName("Form")
public class Form extends AVObject {
public Form() {
super();
}

public void putTypeName(String value) {
    this.put("typeName", value);
}

public void putContent(String value) {
    this.put("content", value);
}

public void putUserId(String value) {
    this.put("user", value);
}

public void putFormTypeId(String value) {
    this.put("type", value);
}

}


D/===AVOS Cloud===: LogUtil$avlog->d->43: curl -X POST -H "X-LC-Id: xxx" -H "X-LC-Key: YourAppKey" -H "X-LC-Session: xxx" -H "Content-Type: application/json" -d '{"requests":[{"body":{"startCity":null,"remark":"","city":null,"forms":{"objects":[{"type":"Pointer","className":"Form"}],"op":"Add"},"date":"","children":[],"user":"5c02b20467f3560066f8a9f2","internalId":"8a71e98d-6ae7-498d-a1e2-8751a27c242b"},"path":"/1.1/classes/Test_Android_Travel","new":true,"method":"POST"}]}' https://izm5frc6.api.lncld.net/1.1/batch/save

D/===AVOS Cloud===: LogUtil$avlog->d->43: {"code":106,"error":"Malformed pointer. Pointers must be arrays of a classname and an object id."}

看起来加黑的是关键报错信息,REST API 请求没有提供对应的 object id。

回过头去看代码:

Form form = new Form();
// 省略
form.putFormTypeId(formType.getObjectId());
// 这里没有将 form 保存到云端
forms.add(form);

构造的 AVObject 需要保存到云端,保存到云端后才能有 object id,指针也是通过 class 和 object id 确定指向的对象的。

抱歉,早先没看出来漏了保存这一步。

  1. 那不就要分开两步操作了嘛?一是首先确保保存Forms成功;二是然后才能继续保存Travel,但是这就涉及到事务问题了。
  2. 但是为什么Travel.add(“Forms”, formsList) 能在后端保存成功呢?就是外面多了一层数组包裹着。。。

呃,我说错了。并不需要分两步,云端会自动创建被引用的指针对象。

我也没什么头绪。

我这边试了下,能够成功保存:

Travel travel = new Travel();
Form form1 = new Form();
Form form2 = new Form();
ArrayList<Form> forms = new ArrayList<>();
forms.add(form1);
forms.add(form2);
travel.addAll("forms", forms);
travel.save();

云端控制台的 json:

{
  "ACL": {
    "*": {
      "read": true,
      "write": true
    }
  },
  "forms": [
    {
      "__type": "Pointer",
      "className": "Form",
      "objectId": "5c88a5a3fe88c2006f4f4bed"
    },
    {
      "__type": "Pointer",
      "className": "Form",
      "objectId": "5c88a5a3ac502e00664e4e58"
    }
  ],
  "objectId": "5c88a5a3fe88c20065e61f18",
  "createdAt": "2019-03-13T06:39:31.490Z",
  "updatedAt": "2019-03-13T06:39:31.493Z"
}

无解。。。
直接用你这代码新建线程运行还是106;
改成saveInBackground主线程运行,还是106。。
将AvObject的子类全改成AvObject,依然106...
后台删除了Class建立其他Class还是106。。。
清除数据并且卸载app,换了模拟器、真机,更新了LeanCloud的SDK版本,AS清理了缓存重启还是106。。

您好,请问您的log里面的X-LC-Key是有内容的嘛?
我的X-LC-Key是空白的,但是X-LC-Id是有的

D/===AVOS Cloud===: LogUtil$avlog->d->43: curl -X POST  -H "X-LC-Id: Izm5FrC6UYytOXCk...SK-gzGzoHsz" -H "X-LC-Key: YourAppKey"  -H "X-LC-Session: uz3x1....ozbl8n09jp"  -H "Content-Type: application/json"   -d '{"requests":[{"body":{"forms":[{"__type":"Pointer","className":"Form"},{"__type":"Pointer","className":"Form"}],"__children":[],"__internalId":"5d2b0561-336b-4013-ad9a-3885da571263"},"path":"/1.1/classes/Test_Android_Travel","new":true,"method":"POST"}]}' https://izm5frc6.api.lncld.net/1.1/batch/save

D/===AVOS Cloud===: LogUtil$avlog->d->43: {"code":106,"error":"Malformed pointer. Pointers must be arrays of a classname and an object id."}

只是调试日志隐藏了 Key 而已(因为 Key 属于比较敏感的信息