我正在尝试反序列化以下JSON:
{
"listings": {
"-L19C5OjcDSjMi4-oha-": {
"listing_id": "-L19C5OjcDSjMi4-oha-",
"location": "Edinburgh"
},
"-L19CJrzEpChO_W14YkC": {
"listing_id": "-L19CJrzEpChO_W14YkC",
"location": "Edinburgh",
"messages": {
"Rp7ytJdEvZeMFgpLqeCSzkSeTyf1": {
"-L19V4QpPMCMwGcNaQBG": {
"senderId": "Rp7ytJdEvZeMFgpLqeCSzkSeTyf1",
"senderName": "Albert",
"text": "Hey there"
},
"-L19r0osoet4f9SjBGE7": {
"senderId": "YMM45tgFFvYB7rx9PhC2TE5eW6D2",
"senderName": "David",
"text": "Hi"
}
}
}
},
"-L19ChjPjX1DnfQb28AW": {
"listing_id": "-L19ChjPjX1DnfQb28AW",
"location": "Edinburgh",
"messages": {
"879dUqGuiXSd95QHzfhbSs05IZn2": {
"-L1i6c7sGf3BcF2cCSCu": {
"senderId": "879dUqGuiXSd95QHzfhbSs05IZn2",
"senderName": "Alberto",
"text": "Hello"
}
},
"Rp7ytJdEvZeMFgpLqeCSzkSeTyf1": {
"-L19FGCMuQACjYKCFEwV": {
"senderId": "Rp7ytJdEvZeMFgpLqeCSzkSeTyf1",
"senderName": "Albert",
"text": "Hey"
},
"-L19T_v2Utxhu1mGhz7-": {
"senderId": "YMM45tgFFvYB7rx9PhC2TE5eW6D2",
"senderName": "David",
"text": "Hi"
},
"-L19TbhActGmga4f47Mz": {
"senderId": "Rp7ytJdEvZeMFgpLqeCSzkSeTyf1",
"senderName": "Albert",
"text": "How are you"
}
}
}
},
"-L19Cz1abm1o-JCbiAnN": {
"listing_id": "-L19Cz1abm1o-JCbiAnN",
"location": "Edinburgh"
},
"-L19DMdFx2pXj9-EKCq2": {
"listing_id": "-L19DMdFx2pXj9-EKCq2",
"location": "Edinburgh"
},
"-L19DV67WjguozFE_4dM": {
"listing_id": "-L19DV67WjguozFE_4dM",
"location": "Edinburgh"
}
}
}
为此,我创建了以下记录:
type MessageContent =
{ senderId: string
senderName: string
text: string; }
type Message =
{ timestampId : string
chatMessages : MessageContent;}
type Chat =
{ chatPartnerId : string
Messages : Message array;}
type ListingContent =
{ from : string
landlord_id : string
listing_id : string
location : string
name : string
pic_1_url : string
pic_2_url : string
pic_3_url : string
pic_4_url : string
pic_5_url : string
messages : Chat array
postcode : string
price_per_night : int
to_date : string;
}
type Listing =
{ timestampId : string
chatMessages : ListingContent;}
type City =
{ city : string
listings : Listing array
}
type AllListings =
{ cities : City array;}
type SearchSettings =
{ from : string
location : string
max_price : decimal
min_price : decimal
to_date : string;}
type MatchContent =
{ id : string
location : string;}
type Match =
{timestampId : string
matchContent : MatchContent;}
type DeclinedContent =
{ id : string;
}
type Declined =
{timestampId : string
declinedContent : DeclinedContent;}
type ListingUserContent =
{ listing_id : string
location : string
messages : Chat array;
}
type ListingUser =
{timestampId : string
listingUser : ListingUserContent;}
type UserContent =
{ declined: Declined array
matches : Match array
searchSettings : SearchSettings
user_listings : ListingUser array;
}
接下来,我有以下代码行:
let listings = JsonConvert.DeserializeObject<Types.UserContent>(html)
其中html
是上面显示的JSON字符串。
但是,这会引发以下错误:
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'Types+Declined[]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'declined.-L0tmKVgUcj_a1ubO5Zd', line 1, position 36.
我相信这可能是因为此特定JSON中没有Declined
,但UserContent
记录的所有4个成员都是完全可选的(它们可能都在那里,或者它们都不是在那里)......这就是我做错了吗?如果是这样,我该如何修复它,并允许可选值。
更新:
所以我注释掉了实际进行反序列化的代码,我仍然得到了奇怪的错误,我认为它与我的代码无关
答案 0 :(得分:2)
制作UserContent
条记录Option
类型的成员,并为您的JSON序列化添加TypeConverter
类型的Option
,例如this one设置。
type UserContent =
{ declined: Declined array option
matches : Match array option
searchSettings : SearchSettings option
user_listings : ListingUser array option;
}
type OptionConverter() =
inherit JsonConverter()
override __.CanConvert(t) =
t.IsGenericType && t.GetGenericTypeDefinition() = typedefof<option<_>>
override __.WriteJson(writer, value, serializer) =
let value =
if value |> isNull
then null
else let _,fields = FSharpValue.GetUnionFields(value, value.GetType())
fields.[0]
serializer.Serialize(writer, value)
override __.ReadJson(reader, t, existingValue, serializer) =
let innerType = t.GetGenericArguments().[0]
let innerType =
if innerType.IsValueType
then (typedefof<Nullable<_>>).MakeGenericType([|innerType|])
else innerType
let value = serializer.Deserialize(reader, innerType)
let cases = FSharpType.GetUnionCases(t)
if value |> isNull
then FSharpValue.MakeUnion(cases.[0], [||])
else FSharpValue.MakeUnion(cases.[1], [|value|])
let serializer = JsonSerializer.Create(JsonSerializerSettings(Converters = [| OptionConverter() |]))
use stringReader = new StringReader(html)
use jsonReader = new JsonTextReader(stringReader)
serializer.Deserialize<Types.UserContent>(jsonReader)