代码之家  ›  专栏  ›  技术社区  ›  Rich

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

  •  1
  • Rich  · 技术社区  · 6 年前

    我有以下代码:

    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
    

    我无法理解为什么第二个farm对象被复制,而不是简单地添加到列表中。

    预期结果应为(每个场仅出现一次):

    { "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 回复  |  直到 6 年前
        1
  •  1
  •   Steven Doggart    6 年前

    你只是在创造一个 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 以任何其他方式列出,你会看到相同的重复。它发生的原因是因为你定义了 农场 作为一个 Class ,使其成为引用类型。如果你把它定义为 Structure ,则它将是一个值类型(即类似于基元)。如果它是一个结构,你不需要 新的 关键字,因为该类型的每个变量都将始终是其自己的实例,并且当您将其添加到列表中时,它将始终添加副本而不是引用。我强烈建议您对.NET中值类型和引用类型之间的差异进行一些研究。

    另一方面,让类命名是令人困惑的 农场 . 我认为您可能希望它是单数的,因为类的每个实例只保存关于单个农场的信息。称之为 农场 ,听起来每个都包含一个农场列表。另外,由于您实际上没有在属性的getter和setter中执行任何操作,因此可以利用auto属性来缩短代码并使其更易于阅读和维护:

    Class Farm
        Public Property FarmID As Integer
        Public Property FarmName As String
    End Class
    
        2
  •  3
  •   David    6 年前

    你只有一个 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 第二次。)