You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JsonConvert反序列化SerializeObject生成字符串失败,属性值全为默认值

为什么JsonConvert无法正确反序列化F#结构体?

问题根源

你定义的Point和ObjA结构体中,用val声明的字段默认是私有访问权限,而Json.NET(Newtonsoft.Json)在序列化/反序列化过程中只会处理公共成员。
这就导致调用SerializeObject时,结构体里的id、x、y字段根本没被序列化成JSON内容,最终生成的是一个空的JSON对象{};反序列化时,Json.NET只能创建结构体的默认实例,所有数值字段自然就被设为默认的0或0.0。

可行解决方案

方案1:将字段设为公共

修改结构体定义,给val加上public修饰符,让Json.NET能访问到这些字段:

type Point =
    struct
        val public x : float
        val public y : float
        new(x, y) = 
        {
            x = x
            y = y
        }
     end

type ObjA =
    struct
        val public id : int
        val public point : Point
        new (id, point) = 
        {
            id = id
            point = point
        }
     end

方案2:使用[<CLIMutable>]属性

给结构体添加[<CLIMutable>]属性,这个属性会让F#自动生成公共属性和无参构造函数,完美适配Json.NET这类序列化库:

[<CLIMutable>]
type Point =
    struct
        val x : float
        val y : float
        new(x, y) = 
        {
            x = x
            y = y
        }
     end

[<CLIMutable>]
type ObjA =
    struct
        val id : int
        val point : Point
        new (id, point) = 
        {
            id = id
            point = point
        }
     end

方案3:改用F#记录类型(推荐)

如果不需要结构体的值类型特性,F#的记录类型默认就支持CLIMutable,序列化反序列化更简洁省心:

type Point = { x : float; y : float }
type ObjA = { id : int; point : Point }

使用示例:

let p = { x = 1.9; y = 2.5 }
let serializedStr = JsonConvert.SerializeObject({ id = 1; point = p })
let deserializedObj = JsonConvert.DeserializeObject<ObjA>(serializedStr)
printfn "ID = %d" deserializedObj.id // 输出1

内容的提问来源于stack exchange,提问作者quincy783

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 20:34:54