F # JSON Type Provider, не сериализуйте нулевые значения - PullRequest
0 голосов
/ 03 мая 2018

Фон

Я использую провайдер JSON-типа FSharp.Data с образцом, который имеет массив объектов, которые могут иметь разные свойства. Вот иллюстративный пример:

[<Literal>]
let sample = """
    { "input": [
        { "name": "Mickey" },
        { "year": 1928 }
       ] 
    }
"""
type InputTypes = JsonProvider< sample >

Поставщик JSON-типов создает тип Input, который имеет необязательное имя и необязательное свойство Year. Это хорошо работает.

Задача

Когда я пытаюсь передать экземпляр этого в веб-сервис, я делаю что-то вроде этого:

InputTypes.Root(
    [|
        InputTypes.Input(Some("Mouse"), None)
        InputTypes.Input(None, Some(2028))
    |]
)

Веб-служба получает следующее и задыхается от нулей.

{
  "input": [
    {
      "name": "Mouse",
      "year": null
    },
    {
      "name": null,
      "year": 2028
    }
  ]
}

Что я пытался

Я считаю, что это работает:

InputTypes.Root(
    [|
        InputTypes.Input(JsonValue.Parse("""{ "name": "Mouse" }"""))
        InputTypes.Input(JsonValue.Parse("""{ "year": 2028 }"""))
    |]
)

Это отправляет это:

{
  "input": [
    {
      "name": "Mouse"
    },
    {
      "year": 2028
    }
  ]
}

Однако в моем реальном проекте структуры больше и требуют намного более условного построения строки JSON. Это своего рода побеждает цель.

Вопросы

  • Есть ли способ заставить поставщика типов JSON не сериализовать нулевые свойства?
  • Есть ли способ заставить поставщика типов JSON не сериализовать пустые массивы?

Для сравнения: библиотека Newtonsoft.JSON имеет атрибут NullValueHandling .

1 Ответ

0 голосов
/ 04 мая 2018

Я не думаю, что есть простой способ заставить JSON-форматирование в F # Data отбрасывать поля null - я думаю, что тип не четко различает, что является null, а что отсутствует.

Вы можете исправить это, написав вспомогательную функцию для удаления всех полей null:

let rec dropNullFields = function
  | JsonValue.Record flds ->
      flds 
      |> Array.choose (fun (k, v) -> 
        if v = JsonValue.Null then None else
        Some(k, dropNullFields v) )
      |> JsonValue.Record
  | JsonValue.Array arr -> 
      arr |> Array.map dropNullFields |> JsonValue.Array
  | json -> json

Теперь вы можете сделать следующее и получить желаемый результат:

let json = 
  InputTypes.Root(
      [|
          InputTypes.Input(Some("Mouse"), None)
          InputTypes.Input(None, Some(2028))
      |]
  )

json.JsonValue |> dropNullFields |> sprintf "%O"
...