简体   繁体   English

我应该如何在 F# 项目中从 Refit 序列化 JSON?

[英]How should I serialize JSON from Refit in an F# project?

I'm using Refit in a C# project to create an API client.我在 C# 项目中使用Refit来创建 API 客户端。 I'd prefer to do everything with F# but Refit doesn't fully support F# yet .我更喜欢用 F# 做所有事情,但Refit 还不完全支持 F#

If I create my User model in C# everything is fine but I'd prefer to be able to express which properties are optional and handle them appropriately.如果我在 C# 中创建我的User模型,一切都很好,但我更希望能够表达哪些属性是可选的并适当地处理它们。

If I add FSharp.Core and use FSharpOption<string> or similar then assertions that try to access those members fail with a NullReferenceException but only if the JSON response contains something optional.如果我添加FSharp.Core并使用FSharpOption<string>或类似的,那么尝试访问这些成员的断言将失败并显示NullReferenceExceptionFSharpOption<string>是 JSON 响应包含可选内容。

If I create a separate F# project that contains a User model I always get a NullReferenceException when trying to deserialize.如果我创建一个单独的包含User模型的 F# 项目,我在尝试反序列化时总是会收到NullReferenceException

Admittedly, keeping any models as part of the C# project seems easier but I don't want to sacrifice knowing which members are optional on the F# side.诚然,将任何模型保留为 C# 项目的一部分似乎更容易,但我不想牺牲知道哪些成员在 F# 方面是可选的。

What is the best way to go about this?解决这个问题的最佳方法是什么?

My current thinking is to leave the C# project as-is and create an F# wrapper which returns models in a Result type, with optional members where appropriate.我目前的想法是保留 C# 项目的原样并创建一个 F# 包装器,该包装器以Result类型返回模型,并在适当的情况下带有可选成员。


Update:更新:

I ended up doing this and adding the following to my FSharp models:我最终这样做并将以下内容添加到我的 FSharp 模型中:

static member ToCSharp :
    user: User
       -> CSharp.User

static member FromCSharp :
    user: CSharp.User
       -> User option

I'm not sure if this will work, but Refit allows you to specify custom serializer settings , which will allow you to try this approach: Serializing F# Option types .我不确定这是否可行,但 Refit 允许您指定自定义序列化程序设置,这将允许您尝试这种方法: 序列化 F# 选项类型

If that doesn't work, create a small repro project and create an issue and I'll look into it.如果这不起作用,请创建一个小的重现项目并创建一个问题,我会调查它。

I'm not familiar with Refit but here's some FSharpOption<> converter code we use in production https://gist.github.com/NickJosevski/956246019c431630931b我不熟悉FSharpOption<>但这里有一些我们在生产中使用的FSharpOption<>转换器代码https://gist.github.com/NickJosevski/956246019c431630931b

For JSON.net we add that FSharpOptionConverter to the list of converters that json.net takes.对于JSON.net我们添加FSharpOptionConverter到转换器的列表json.net需要。

From the docs on refit I see a this note:改装的文档中,我看到了一个注释:

When creating a Refit generated live interface, you may optionally pass a RefitSettings that will allow you to specify what serializer settings you would like.在创建 Refit 生成的实时界面时,您可以选择传递 RefitSettings 以允许您指定所需的序列化程序设置。 This allows you to have different serializer settings for separate APIs这允许您为单独的 API 设置不同的序列化程序

So in my code the JsonSerializerSettings setup is like this:所以在我的代码中 JsonSerializerSettings 设置是这样的:

var settings = new JsonSerializerSettings()
{
    TypeNameHandling = TypeNameHandling.Auto,
    ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
    Formatting = Formatting.Indented
};

// important bit:
 settings.Converters.Add(new FSharpOptionConverter());

So if you can find the right place to get those settings wired up then deserializion should be fine for FSharpOption<> .因此,如果您能找到正确的位置来连接这些设置,那么对于FSharpOption<>反序列化应该FSharpOption<>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM