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

时间:2017-11-24 15:25:02

标签: json azure enums azure-cosmosdb azure-functions

我在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();

“tick”是要存储的上述对象。

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

  • 枚举属性中的注释:

    [Newtonsoft.Json.JsonConverter(typeof(StringEnumConverter))]
    public OrderActionEnum? Action { get; set; }
    
  • enum defintion的注释:

    [Newtonsoft.Json.JsonConverter(typeof(StringEnumConverter))]
    public enum OrderActionEnum
    {
        NEW,
        CHANGE,
        DELETE,
        SNAPSHOT,
        INITIAL
    }
    
  • 将转换器传递给文档db client的构造函数:

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

    JsonConvert.DefaultSettings = () => new JsonSerializerSettings
    {
       Converters = new List<JsonConverter> {new StringEnumConverter()}
    };
    

这些尝试都没有说服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)

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

现在我的想法已经不多了。我可以用普通字符串替换枚举,但我真的不想这样做。任何提示都表示赞赏。

我知道之前有过类似的问题。例如:

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

2 个答案:

答案 0 :(得分:1)

我找到了解决问题的解决方法:

  • 将应该保存的对象序列化为json字符串...
  • ...然后将其反序列化为通用的JObject ...
  • ...然后保存。

代码如下所示:

DocumentClient = new DocumentClient(new Uri(dbServiceEndpoint), dbAuthKey);
...
var jsonString = JsonConvert.SerializeObject(tick);
var jObject = JsonConvert.DeserializeObject(jsonString);
var response = DocumentClient.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri(DatabaseId, CollectionId), jObject);
response.Wait();

通过这种方法将枚举转换为纯字符串。不是很好,但毕竟我很满意这个解决方案。至少我不需要改变任何其他地方。

答案 1 :(得分: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);
}

绑定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
}

制作文件:

{
  "id": "111",
  "Action": "CHANGE"
}
相关问题