Десериализация Json не работает в F# с использованием Newtonsoft.Json после обновления до .Net 6

Это мои типы:

[<DataContract>]
type AreaCodeSingleResponse = 
    { [<field:DataMember(Name = "id")>]
      Id : string
      [<field:DataMember(Name = "code")>]
      Code : string
      [<field:DataMember(Name = "name")>]
      Name : string }

[<DataContract>]
type AreaCodeListResponse = 
    { 
    [<field:DataMember(Name = "areacode_list")>]
      AreaCodeList : List<AreaCodeSingleResponse> }

Это образец данных:

{
    "areacode_list": [
        {
            "id": "00447",
            "code": "07",
            "name": "UK Mobile",
            "order_column": "_00447"
        },
        {
            "id": "0044113",
            "code": "0113",
            "name": "Leeds",
            "order_column": "0044113"
        }
    ]
}

Это код десериализации, где вызывается передача типа AreaCodeListResponse:

member __.ReturnDataToType<'T>() =
    __.ReturnData
    |> JsonConvert.DeserializeObject<'T>

До того, как я обновился до DotNet6, все работало нормально и возвращало список данных. После этого он терпит неудачу и возвращает пустой список. Ошибок нет, но список пуст.

Это не удается для всех моих других вызовов десериализации с использованием класса и других типов.

Изменилось ли что-нибудь, о чем мне нужно знать? Я не эксперт F#, просто работаю над каким-то устаревшим кодом.

Нет, определенно используется JSON.net, это специально указано в коде.

John McArthur 24.12.2022 16:16

У меня нет f# на .NET 6 для тестирования, но что, если вы измените [<field:DataMember(Name = "areacode_list")>] на [<DataMember(Name = "areacode_list")>]?

dbc 24.12.2022 19:06

На самом деле, критическое изменение, похоже, происходит при переходе с .net 6.0 на 7.0. У меня ваш подход работает с версиями Newtonsoft.Json 13.0.2, 12.0.3 и 11.0.2 (более ранние не пробовал) в .net 6.0, но уже не в .net 7.0. Каков результат dotnet --version в вашем окружении?

jpe 29.12.2022 18:05
Как сделать HTTP-запрос в Javascript?
Как сделать HTTP-запрос в Javascript?
В JavaScript вы можете сделать HTTP-запрос, используя объект XMLHttpRequest или более новый API fetch. Вот пример для обоих методов:
5
4
103
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Судя по всему, изменилось поведение в том, как среда выполнения .Net обрабатывает OptionalFieldAttribute (используется как field: в F#) в .Net 7 (в сочетании с записями F#). При просмотре документации OptionalFieldAttribute он не должен иметь значимого эффекта в контексте сериализации/десериализации JSON и, следовательно, должен быть удален. Следующий код работает, создавая список экземпляров записей AreaCodeSingleResponse. Минимальная модификация, позволяющая заставить код в вопросе работать, — удалить OptionalFieldAttribute из поля AreaCodeList.

#r "nuget:Newtonsoft.Json,Version=13.0.2"

open System.Runtime.Serialization
open Newtonsoft.Json

[<DataContract>]
type AreaCodeSingleResponse = 
    { 
      [<DataMember(Name = "id")>]
      Id : string
      
      [<DataMember(Name = "code")>]
      Code : string
      
      [<DataMember(Name = "name")>]
      Name : string
      }

[<DataContract>]
type AreaCodeListResponse = 
    { 
      //Remove the OptionalFieldAttribute:
      //[<field:DataMember(Name = "areacode_list")>]
      [<DataMember(Name = "areacode_list")>]
      AreaCodeList : List<AreaCodeSingleResponse>
    }


let ReturnData = """{
    "areacode_list": [
        {
            "id": "00447",
            "code": "07",
            "name": "UK Mobile",
            "order_column": "_00447"
        },
        {
            "id": "0044113",
            "code": "0113",
            "name": "Leeds",
            "order_column": "0044113"
        }
    ]
}"""
ReturnData |> JsonConvert.DeserializeObject<AreaCodeListResponse> |> printf "%A"

Вопрос, почему происходит такое изменение поведения при переходе с .Net runtime 6.0.201 на .Net 7.0.101, остается открытым.

Другие вопросы по теме