我有以下代码:
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"
}
]
}
因此,“九至六农场”出现了两次,而没有“一至四农场”的踪迹。
我已经盯着这个看了好几个小时,谁能告诉我我在做什么错?!
答案 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