添加到JSON对象的ASP.NET(VB)数组/列表项被复制

时间:2018-08-03 12:56:39

标签: asp.net arrays json vb.net

我有以下代码:

Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq

Class Farms

    Public Property farmID As Integer
        Get
            Return _sfarmID
        End Get
        Set(value As Integer)
            _sfarmID = value
        End Set
    End Property
    Private _sfarmID As Integer

    Public Property farmName As String
        Get
            Return _farmName
        End Get
        Set(value As String)
            _farmName = value
        End Set
    End Property
    Private _farmName As String

End Class


Partial Class credentials_check_test
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load

        Dim result As String = "OK"
        Dim emailAddressEncrypted = "d2839280b3b1f3692a94ac76c6a5"
        Dim passwordEncrypted = "524efa0ab3c32c63b470efc4ec69"

        Dim objFarms = New List(Of Farms)()
        Dim farms = New Farms()

        farms.farmID = 1234
        farms.farmName = "One to Four Farm"
        objFarms.Add(farms)

        farms.farmID = 9876
        farms.farmName = "Nine to Six Farm"
        objFarms.Add(farms)

        Response.Write(JsonConvert.SerializeObject(
                       New With {
                           result, emailAddressEncrypted, passwordEncrypted, .farmList = objFarms
                                                                         }, Formatting.Indented))

    End Sub

End Class

我不明白为什么要复制第二个服务器场对象,而不是简单地将其添加到列表中。

预期结果应该是(每个服务器场仅出现一次):

{ "result": "OK", "emailAddressEncrypted": "d5d2839280b3b1f3692a94ac76c6a5b4", "passwordEncrypted": "75524efa0ab3c32c63b470efc4ec69e4", "farmList": [{ "farmID": 1234, "farmName": "One to Four Farm" }, { "farmID": 9876, "farmName": "Nine to Six Farm" } ] }

但是我的实际结果是(请注意,农场ID 9876出现了两次!):

{ "result": "OK", "emailAddressEncrypted": "d2839280b3b1f3692a94ac76c6a5", "passwordEncrypted": "524efa0ab3c32c63b470efc4ec69", "farmList": [ { "farmID": 9876, "farmName": "Nine to Six Farm" }, { "farmID": 9876, "farmName": "Nine to Six Farm" } ] }

因此,“九至六农场”出现了两次,而没有“一至四农场”的踪迹。

我已经盯着这个看了好几个小时,谁能告诉我我在做什么错?!

2 个答案:

答案 0 :(得分:3)

您只有一个Farms对象:

Dim farms = New Farms()

您将两次添加到列表,然后对其属性进行两次修改。该对象将始终显示您为其设置的最后一个值,并且对该对象的任何引用(包括列表元素)都将显示相同的状态。

在列表中创建两个对象:

Dim farms = New Farms()

farms.farmID = 1234
farms.farmName = "One to Four Farm"
objFarms.Add(farms)

farms = New Farms() ' -- create a new one here

farms.farmID = 9876
farms.farmName = "Nine to Six Farm"
objFarms.Add(farms)

(附带说明:这确实与JSON序列化无关。在调试器中单步执行代码,观察对象的运行时值,并查看在farms上设置属性后会发生什么情况第二次。)

答案 1 :(得分:1)

您仅创建一个Farms对象。这是创建对象的行:

Dim farms = New Farms()

New关键字告诉它创建对象。由于您在第二次填充之前从未将其设置为等于新对象,因此您要做的就是修改(覆盖)原始对象的属性,然后再次将其添加到列表中。此时,列表仅包含对同一对象的两个引用。

要修复此问题,您需要先将其设置为新对象,然后再填充第二组数据:

Dim farms = New Farms()
farms.farmID = 1234
farms.farmName = "One to Four Farm"
objFarms.Add(farms)

farms = New Farms()
farms.farmID = 9876
farms.farmName = "Nine to Six Farm"
objFarms.Add(farms)

或者,您可以使用其他变量名称:

Dim farms = New Farms()
farms.farmID = 1234
farms.farmName = "One to Four Farm"
objFarms.Add(farms)

Dim farms2 = New Farms()
farms2.farmID = 9876
farms2.farmName = "Nine to Six Farm"
objFarms.Add(farms2)

或者更好的是,根本不创建变量,而只是使用对象初始化语法填充新对象:

objFarms.Add(New Farms() With {.farmID = 1234, .farmName = "One to Four Farm"})
objFarms.Add(New Farms() With {.farmID = 9876, .farmName = "Nine to Six Farm"})

正如David提到的,这与JSON序列化无关。如果您以任何其他方式查看或输出objFarms列表的内容,将会看到相同的重复项。发生这种情况的原因是因为您将Farms定义为Class,这使其成为了引用类型。如果您将其定义为Structure,则它将是一个值类型(即像原始图元)。如果是结构,则不需要New关键字,因为该类型的每个变量都将始终是其自己的实例,并且在将其添加到列表中时,它将始终添加一个副本而不是参考。我强烈建议您对.NET中的值类型和引用类型之间的差异进行一些研究。

另一方面,将类命名为Farms令人困惑。我认为您可能希望单数形式,因为该类的每个实例仅保存有关单个服务器场的信息。通过将其命名为Farms,听起来每个人都会包含一个农场列表。另外,由于实际上并没有在属性的getter和setter中做任何事情,因此您可以利用自动属性来缩短代码并使其更易于阅读和维护:

Class Farm
    Public Property FarmID As Integer
    Public Property FarmName As String
End Class