Cosmos / Document Db 客户端忽略枚举的 JsonConverter

Mar*_*enk 5 enums json azure azure-functions azure-cosmosdb

我正在 Azure 中使用 Cosmos DB 的 DocumentDB API。文档从 EventHub 获取,并由该 EventHub 触发的 Azure 函数存储到数据库中。

我保存的文档还包含几个枚举。不幸的是,这些枚举值是使用索引号而不是枚举值进行序列化的(请参见此处: https: //i.stack.imgur.com/3nP9o.png)。或者,更准确地说,这是该函数在 Azure 中运行时发生的情况。本地 IDE 中的测试运行良好。

这是写入 Cosmos/DocumentDB 的代码:

DocumentClient = new DocumentClient(new Uri(dbServiceEndpoint), dbAuthKey);
...
var response =  DocumentClient.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri(DatabaseId, CollectionId), tick);
response.Wait();
Run Code Online (Sandbox Code Playgroud)

“tick”是提到的要存储的对象。

我尝试了一些方法来使文档客户端正确序列化枚举:

  • 枚举属性的注释:

    [Newtonsoft.Json.JsonConverter(typeof(StringEnumConverter))]
    public OrderActionEnum? Action { get; set; }
    
    Run Code Online (Sandbox Code Playgroud)
  • 枚举定义处的注释:

    [Newtonsoft.Json.JsonConverter(typeof(StringEnumConverter))]
    public enum OrderActionEnum
    {
        NEW,
        CHANGE,
        DELETE,
        SNAPSHOT,
        INITIAL
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 将转换器传递给文档数据库客户端的构造函数:

    DocumentClient = new DocumentClient(new Uri(dbServiceEndpoint), dbAuthKey,                
        new JsonSerializerSettings
        {
            Converters = new List<JsonConverter> {new StringEnumConverter()}
        });
    
    Run Code Online (Sandbox Code Playgroud)
  • 设置默认序列化器:

    JsonConvert.DefaultSettings = () => new JsonSerializerSettings
    {
       Converters = new List<JsonConverter> {new StringEnumConverter()}
    };
    
    Run Code Online (Sandbox Code Playgroud)

这些尝试都没有说服 Cosmos/DocumentDB 存储枚举值。

一个有趣的影响是,第三个变体(将转换器传递给 DocumentClient 的构造函数)在运行 Azure 时导致异常(本地测试工作正常):

2017-11-24T15:08:55.291 System.MissingMethodException : Method not found: 'Void Microsoft.Azure.Documents.Client.DocumentClient..ctor(System.Uri, System.String, Newtonsoft.Json.JsonSerializerSettings, Microsoft.Azure.Documents.Client.ConnectionPolicy, System.Nullable`1<Microsoft.Azure.Documents.ConsistencyLevel>)'.
   at TickAnalysis.DataManager.Persistency.AbstractCosmosClient`1..ctor(ILogger logger,String dbServiceEndpoint,String dbAuthKey,String databaseId,String collectionId)
   at TickAnalysis.DataManager.DataManagerFunction.RunStoreOrderEvent(String message,TraceWriter log)
Run Code Online (Sandbox Code Playgroud)

这看起来有点像正在使用 Microsoft.Azure.DocumentDB 包的不同版本。因此,我将本地 bin 中的 DLL 与 Azure 中为该函数部署的 DLL 进行了比较。在这两种情况下,版本都是 1.19.1。

现在我已经没有主意了。我可以用纯字符串替换枚举,但我真的不想这样做。任何提示表示赞赏。

我知道以前也有人问过类似的问题。例如:

不幸的是这些都没有解决我的问题。

Mik*_*kov 0

您应该使用 Azure Functions Cosmos DB 输出绑定来保存文档。以下示例按您的预期工作(将枚举值保存为字符串)。

代码run.csx

#r "Newtonsoft.Json"

using System.Net;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

public class Doc
{
    public string id { get; set; }

    [JsonConverter(typeof(StringEnumConverter))]
    public OrderActionEnum Action { get; set; }
}

public enum OrderActionEnum { NEW, CHANGE }

public static HttpResponseMessage Run(HttpRequestMessage req, out Doc outputDocument)
{
    outputDocument = new Doc { id = "111", Action = OrderActionEnum.CHANGE };
    return req.CreateResponse(HttpStatusCode.OK);
}
Run Code Online (Sandbox Code Playgroud)

绑定function.json

{
  "bindings": [
    {
      "authLevel": "function",
      "name": "req",
      "type": "httpTrigger",
      "direction": "in"
    },
    {
      "name": "$return",
      "type": "http",
      "direction": "out"
    },
    {
      "type": "documentDB",
      "name": "outputDocument",
      "databaseName": "testdb",
      "collectionName": "test",
      "createIfNotExists": false,
      "connection": "my_DOCUMENTDB",
      "direction": "out"
    }
  ],
  "disabled": false
}
Run Code Online (Sandbox Code Playgroud)

制作文件:

{
  "bindings": [
    {
      "authLevel": "function",
      "name": "req",
      "type": "httpTrigger",
      "direction": "in"
    },
    {
      "name": "$return",
      "type": "http",
      "direction": "out"
    },
    {
      "type": "documentDB",
      "name": "outputDocument",
      "databaseName": "testdb",
      "collectionName": "test",
      "createIfNotExists": false,
      "connection": "my_DOCUMENTDB",
      "direction": "out"
    }
  ],
  "disabled": false
}
Run Code Online (Sandbox Code Playgroud)