Unique ID在反序列化JSON时被更改 – 应保持不变。

huangapple go评论120阅读模式
英文:

Unique ID being changed when deserializing JSON - it should stay the same

问题

在构造函数触发时生成一个新的唯一ID。然而,当我对其进行序列化然后反序列化时,我的ID再次生成,因为它似乎又创建了一个新对象。停止此行为的最简单方法是什么?(如果可能的话,我想保留构造函数中的唯一guid生成)

<Serializable>
Public Class YubikeyPool
    Public ReadOnly Property ID As Guid
    Public Property Name As String

    Public Sub New()
        ' 在反序列化时不要重新生成ID
        If Not System.Runtime.Serialization.FormatterServices.IsConstructorInvocation Then
            ID = Guid.NewGuid()
        End If
    End Sub

    Public Overrides Function ToString() As String
        Return Name
    End Function
End Class

这里是我的序列化/反序列化函数:

Function Serialize(ByVal objData As Object) As Byte()
    If objData Is Nothing Then Return Nothing
    Return Encoding.UTF8.GetBytes(JsonSerializer.Serialize(objData, GetJsonSerializerOptions()))
End Function

Function Deserialize(Of T)(ByVal byteArray As Byte()) As T
    If byteArray Is Nothing OrElse Not byteArray.Any() Then Return Nothing
    Return JsonSerializer.Deserialize(Of T)(byteArray, GetJsonSerializerOptions())
End Function

Private Function GetJsonSerializerOptions() As JsonSerializerOptions
    Dim options = New JsonSerializerOptions
    With options
        .PropertyNamingPolicy = Nothing
        .WriteIndented = True
        .AllowTrailingCommas = True
        .DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
    End With

    Return options
End Function

请注意,我在构造函数中添加了一个条件,以确保只有在反序列化时才会生成新的ID。这样,当您进行序列化和反序列化时,ID将保持不变。

英文:

I have a small class in which when the constructor is fired it generates a new unique ID. However, when I serialize it and then deserialize it my ID is being generated again because it seems to be creating a new object again. What is the easiest way to stop this behavior? (I would like to keep the unique guid generation in the constructor if possible)

 &lt;Serializable&gt;
    Public Class YubikeyPool
        Public ReadOnly Property ID As Guid
        Public Property Name As String

        Public Sub New()
            ID = Guid.NewGuid()
        End Sub
       
        Public Overrides Function ToString() As String
            Return Name
        End Function
    End Class

Here is my Serialize/Deserialize functions

 Function Serialize(ByVal objData As Object) As Byte()
    If objData Is Nothing Then Return Nothing
    Return Encoding.UTF8.GetBytes(JsonSerializer.Serialize(objData, GetJsonSerializerOptions()))
End Function

Function Deserialize(Of T)(ByVal byteArray As Byte()) As T
    If byteArray Is Nothing OrElse Not byteArray.Any() Then Return Nothing
    Return JsonSerializer.Deserialize(Of T)(byteArray, GetJsonSerializerOptions())
End Function

Private Function GetJsonSerializerOptions() As JsonSerializerOptions
    Dim options = New JsonSerializerOptions
    With options
        .PropertyNamingPolicy = Nothing
        .WriteIndented = True
        .AllowTrailingCommas = True
        .DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
    End With

    Return options
End Function

答案1

得分: 3

构造函数将会运行。保留先前值的唯一方法是覆盖构造函数的工作,并在反序列化时设置该值以及其他属性...但目前无法进行此操作,因为该属性标记为ReadOnly。首先移除该修饰符。

英文:

The constructor WILL run. The only way to keep a prior value is to overwrite the constructor's work and the set the value along with other properties when you deserialize... which can't happen right now because the property is marked ReadOnly. Start by removing that modifier.

答案2

得分: 0

You can probably make a little change to your class definition, using an overloaded Constructor and decorating the default Constructor with [JsonConstructorAttribute]

你可以对你的类定义进行一些小的更改,使用一个重载的构造函数,并在默认构造函数上添加 [JsonConstructorAttribute]

The read-only property (here, the property has a private setter) can be decorated with a [JsonIncludeAttribute]. In this case, the non-public setter is used. For example:

只读属性(这里属性具有private setter)可以使用[JsonIncludeAttribute]进行修饰。在这种情况下,将使用非公共的setter。例如:

(in C#, since you have tagged this language)
(在C#中,因为您标记了这种语言)

[Serializable]
public class YubikeyPool {
    [System.Text.Json.Serialization.JsonInclude]
    public Guid ID { get; private set; }

    public string Name { get; set; }

    [System.Text.Json.Serialization.JsonConstructor]
    public YubikeyPool() : this(string.Empty) { }

    public YubikeyPool(string name) =&gt; ID = Guid.NewGuid();

    public override string ToString() =&gt; Name;
}

You can initialize a class object as you were probably doing.

您可以像之前一样初始化一个类对象。

var yp = new YubikeyPool() { Name = "Some Name" };

The previously auto-generated GUID is preserved when deserializing

在反序列化时,之前自动生成的GUID将被保留

I think the method used for serialization should be changed in:

我认为用于序列化的方法应该进行更改:

public byte[] Serialize<T>(T objData) where T : class {
    if (objData is null) return null;
    return Encoding.UTF8.GetBytes(JsonSerializer.Serialize(objData, GetJsonSerializerOptions()));
}

VB.NET version:

VB.NET版本:

<Serializable>
Public Class YubikeyPool
    Private m_ID As Guid

    <JsonInclude>
    Public Property ID As Guid
        Get
            Return m_ID
        End Get
        Private Set()
            m_ID = Value
        End Set
    End Property

    Public Property Name As String

    <JsonConstructor>
    Public Sub New()
        Me.New(String.Empty)
    End Sub

    Public Sub New(name As String)
        Me.Name = name
        ID = Guid.NewGuid()
    End Sub

    Public Overrides Function ToString() As String
        Return Name
    End Function
End Class
Public Function Serialize(Of T As Class)(objData As T) As Byte()
    If objData Is Nothing Then Return Nothing
    Return Encoding.UTF8.GetBytes(JsonSerializer.Serialize(objData, GetJsonSerializerOptions()))
End Function

以上是您提供的代码部分的翻译。

英文:

You can probably make a little change to your class definition, using an overloaded Constructor and decorating the default Constructor with [JsonConstructorAttribute]

The read-only property (here, the property has a private setter) can be decorated with a [JsonIncludeAttribute]. In this case, the non-public setter is used. For example:

(in C#, since you have tagged this language)
Assuming System.Text.Json 7.0.0.3

[Serializable]
public class YubikeyPool {
    [System.Text.Json.Serialization.JsonInclude]
    public Guid ID { get; private set; }

    public string Name { get; set; }

    [System.Text.Json.Serialization.JsonConstructor]
    public YubikeyPool() : this(string.Empty) { }

    public YubikeyPool(string name) =&gt; ID = Guid.NewGuid();

    public override string ToString() =&gt; Name;
}

You can initialize a class object as you were probably doing.

var yp = new YubikeyPool() { Name = &quot;Some Name&quot; };

The previously auto-generated GUID is preserved when deserializing


I think the method used for serialization should be changed in:

public byte[] Serialize&lt;T&gt;(T objData) where T : class {
    if (objData is null) return null;
    return Encoding.UTF8.GetBytes(JsonSerializer.Serialize(objData, GetJsonSerializerOptions()));
}

VB.NET version:

&lt;Serializable&gt;
Public Class YubikeyPool
    Private m_ID As Guid

    &lt;JsonInclude&gt;
    Public Property ID As Guid
        Get
            Return m_ID
        End Get
        Private Set()
            m_ID = Value
        End Set
    End Property

    Public Property Name As String

    &lt;JsonConstructor&gt;
    Public Sub New()
        Me.New(String.Empty)
    End Sub

    Public Sub New(name As String)
        Me.Name = name
        ID = Guid.NewGuid()
    End Sub

    Public Overrides Function ToString() As String
        Return Name
    End Function
End Class

Public Function Serialize(Of T As Class)(objData As T) As Byte()
    If objData Is Nothing Then Return Nothing
    Return Encoding.UTF8.GetBytes(JsonSerializer.Serialize(objData, GetJsonSerializerOptions()))
End Function

huangapple
  • 本文由 发表于 2023年8月5日 03:44:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/76838777.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定