【发布时间】:2023-09-04 05:29:01
【问题描述】:
我创建了一个简单的类模型 (AnchorMetaData),如下所示,其中有两个项目。一个是列表字段 (Vector3),由于它的制作方式而无法序列化,因此我为类 (SerializableVector3) 创建了一个可以序列化和反序列化的属性。我希望在 Newtonsoft 中使用这个属性来保存/加载模型。
该类保存得很好但是,当我尝试从 JSON 反序列化模型时,它调用 AttachedTaskLocations 属性的 getter 而不是 setter。这使得要初始化的字段为空。
我只是通过使用日志消息并设置一些断点才注意到这一点。反序列化时它从不调用设置器。这很奇怪,因为它应该起作用。
另一个奇怪的行为是它确实会在SerializableVector3 的 x、y、z 的设置器上暂停,并使用文件中的正确值。这太奇怪了。
我正在使用 Unity 2019.1.14,但没有它也应该可以工作,只需将矢量列表更改为您拥有的东西。
当我加载显示的 JSON 文件时,该文件是通过序列化 AnchorMetaData 创建的,它在 attachedTaskLocations 中有零项。为什么会这样?为什么 setter 没有被调用?
我创建的用于保存/加载Vector3 的类称为SerializableVector3。
我希望保存/加载的类:
[Serializable]
public class AnchorMetaData
{
// Cannot serialize this.
[JsonIgnore]
public List<Vector3> attachedTaskLocations = new List<Vector3>();
/// <summary>
/// This property servers as an interface for JSON de-/serialization.
/// It uses a class that can be serialized by Newtonsoft.
/// Should not be used in code except for serialization purposes.
/// </summary>
[JsonProperty("AttachedTaskLocations")]
public List<SerializableVector3> AttachedTaskLocations
{
get
{
Debug.Log("Writing serialized vector.");
return attachedTaskLocations
.Select(vector3 => new SerializableVector3(vector3))
.ToList();
}
set
{
Debug.Log("Loading serialized vector.");
attachedTaskLocations = value
.Select(sVector3 => new Vector3(sVector3.x, sVector3.y, sVector3.z))
.ToList();
}
}
}
序列化 JSON:
{
"AttachedTaskLocations": [
{
"x": 1.0,
"y": 1.0,
"z": 1.0
},
{
"x": 1E+12,
"y": 2.0,
"z": 3.0
},
{
"x": 0.0,
"y": 0.0,
"z": 0.0
}
]
}
【问题讨论】:
-
是否有相关/有意只标记
y[JsonProperty]而x和z不是? -
我尝试添加
private List<SerializableVector3> _atl并将 get 更改为{ Debug.Log(...); return _atl; }。我将_atl = value;添加到您拥有的设置器中。现在调用get,然后设置。我尝试了一些变体,如果我在 getter 中除了return _atl;之外还有任何有意义的东西,那么永远不会调用 setter。我认为 Newtonsoft 在使用支持字段序列化属性方面有点太聪明了。 -
我应该说,“它认为可以计算的属性太聪明了”。如果记录在案,也许有一个属性可以修改行为。否则,私有字段解决方案很愚蠢,但很实用,评论很丰富。
-
@EdPlunkett 感谢您抽出宝贵时间进行调查。这有点为我指明了正确的方向。因此,如果 getter 在调用时返回 null,它会调用 setter,否则不会。奇怪,我不知道为什么会这样,但确实如此。很高兴知道。如果您想写一个答案,我可以解决这个问题,直到出现更好的解决方案。
-
顺便说一句,您可以为 Unity 对象(例如 Vector3)使用自定义合约解析器和自定义序列化器。要查找(并阅读相关文档)的类是
DefaultContractResolver和JsonConverter。不幸的是,我在 GitHub 上没有示例,但它非常简单。
标签: c# unity3d serialization json.net deserialization