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

使用存储过程向Cosmos DB写入数据时遇文档格式错误求助

问题排查:Azure Cosmos DB存储过程批量写入ChargeTransaction数据报错

错误信息

{"Errors":["Encountered exception while executing Javascript. Exception = Error: The document body must be an object or a string representing a JSON-serialized object.\r\nStack trace: Error: The document body must be an object or a string representing a JSON-serialized object.\n   at createDocument (script.js:644:21)\n   at tryCreate (script.js:20:9)\n   at createToDoItems (script.js:15:5)\n   at __docDbMain (script.js:37:5)\n   at Global code (script.js:1:2)"]},"statusCode":400,"subStatusCode":400,"isGone":false,"isNotFound":false,"isInvalidPartition":false,"isThroughputControlRequestRateTooLarge":false,"requestCharge":3.45,"itemLSN":-1,"sessionToken":"0:-1#244878","backendLatencyInMs":2.457,"exceptionMessage":"[\"Encountered exception while executing Javascript. Exception = Error: The document body must be an object or a string representing a JSON-serialized object.\\r\\nStack trace: Error: The document body must be an object or a string representing a JSON-serialized object.\\n   at createDocument (script.js:644:21)\\n   at tryCreate (script.js:20:9)\\n   at createToDoItems (script.js:15:5)\\n   at __docDbMain (script.js:37:5)\\n   at Global code (script.js:1:2)\"]"

相关代码

Java调用代码

List<ChargeTransaction> chargeTransactionList = new ArrayList<>();
for (ChargeTransaction chargeTransaction :
    getChargeTransactions(event, chargeTransactionList)) {
    list.add(chargeTransaction);
}
 CosmosStoredProcedureProperties definition;
try {
    ClassPathResource resource = new ClassPathResource("createEvent.js");
    InputStream inputStream = resource.getInputStream();
    String result = IOUtils.toString(inputStream, StandardCharsets.UTF_8);

    definition = new CosmosStoredProcedureProperties(
            "spCreateEvent",
            result
        );
    CosmosStoredProcedureResponse response = container
            .getScripts()
            .createStoredProcedure(definition);
CosmosStoredProcedure sproc = container   
        .getScripts()
        .getStoredProcedure("spCreateEvent");

CosmosStoredProcedureRequestOptions options = new CosmosStoredProcedureRequestOptions();
options.setPartitionKey(
    new PartitionKey(event.getEventPayload().getOriginOrderNo())
);

CosmosStoredProcedureResponse response = sproc.execute(
        list,
    options
);
System.out.println(response.getStatusCode());
  }catch(Exception e) {
      e.printStackTrace();
  }

存储过程代码(createEvent.js)

function createToDoItems(items) {
var collection = getContext().getCollection();
var collectionLink = collection.getSelfLink();
var count = 0;

if (!items) throw new Error("The array is undefined or null.");

var numItems = items.length;

if (numItems == 0) {
    getContext().getResponse().setBody(0);
    return;
}

tryCreate(items[count], callback);

function tryCreate(item, callback) {
    var options = { disableAutomaticIdGeneration: false };

    var isAccepted = collection.createDocument(collectionLink, item, options, callback);

    if (!isAccepted) getContext().getResponse().setBody(count);
}

function callback(err, item, options) {
    if (err) throw err;
    count++;
    if (count >= numItems) {
        getContext().getResponse().setBody(count);
    } else {
        tryCreate(items[count], callback);
    }
}
}

问题根因

错误提示明确指出文档主体必须是对象或JSON序列化对象的字符串,问题出在Java代码向存储过程传递参数的环节:直接传递List<ChargeTransaction>对象列表时,Cosmos DB Java SDK没有将其正确序列化为存储过程可识别的JSON对象数组,导致存储过程中items参数不是合法的JSON结构,调用collection.createDocument时触发校验错误。

解决方案

1. 修改Java代码:将对象序列化为JSON字符串传递

使用JSON序列化库(如Jackson)将ChargeTransaction列表转换为JSON数组字符串,再传递给存储过程。

修改后的Java关键代码:

// 导入Jackson的ObjectMapper
import com.fasterxml.jackson.databind.ObjectMapper;

// ... 原有代码 ...

// 将ChargeTransaction列表序列化为JSON字符串
ObjectMapper objectMapper = new ObjectMapper();
String itemsJson = objectMapper.writeValueAsString(list);

// 调用存储过程时传入JSON字符串
CosmosStoredProcedureResponse response = sproc.execute(
        itemsJson,
        options
);

2. 修改存储过程:解析JSON字符串为对象数组

存储过程接收JSON字符串后,先解析为对象数组再进行批量写入操作。

修改后的createEvent.js:

function createToDoItems(itemsJson) {
var collection = getContext().getCollection();
var collectionLink = collection.getSelfLink();
var count = 0;

if (!itemsJson) throw new Error("The JSON string is undefined or null.");

// 解析JSON字符串为对象数组
var items = JSON.parse(itemsJson);
var numItems = items.length;

if (numItems == 0) {
    getContext().getResponse().setBody(0);
    return;
}

tryCreate(items[count], callback);

function tryCreate(item, callback) {
    var options = { disableAutomaticIdGeneration: false };

    var isAccepted = collection.createDocument(collectionLink, item, options, callback);

    if (!isAccepted) getContext().getResponse().setBody(count);
}

function callback(err, item, options) {
    if (err) throw err;
    count++;
    if (count >= numItems) {
        getContext().getResponse().setBody(count);
    } else {
        tryCreate(items[count], callback);
    }
}
}

额外注意事项

  • 确保ChargeTransaction类的字段都能被Jackson正确序列化(如无私有字段未提供getter,无循环引用等)。
  • 存储过程创建时需确保使用正确的分区键上下文,本次调用已设置PartitionKey,需保证所有ChargeTransaction对象的分区键字段值与调用时的OriginOrderNo一致,避免跨分区写入错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 22:32:21