MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Visual Basic JSON格式解析全攻略

2024-08-227.9k 阅读

一、JSON 基础概述

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,以易于阅读和编写的文本格式来表示结构化数据。它基于 JavaScript 的一个子集,但如今已被多种编程语言广泛支持。

JSON 数据结构主要有两种形式:对象和数组。对象是一个无序的键值对集合,用花括号 {} 包围,键和值之间用冒号 : 分隔,不同键值对之间用逗号 , 分隔。例如:

{
    "name": "John",
    "age": 30,
    "city": "New York"
}

数组是一个有序的值列表,用方括号 [] 包围,数组元素之间用逗号 , 分隔。例如:

[10, 20, 30]

JSON 值可以是以下几种类型:

  1. 字符串:用双引号 " 包围的 Unicode 字符序列,例如 "Hello, World!"
  2. 数字:整数或浮点数,例如 423.14
  3. 布尔值truefalse
  4. 对象:前面提到的键值对集合。
  5. 数组:有序值列表。
  6. null:表示空值。

二、Visual Basic 中解析 JSON 的常用库

在 Visual Basic 中,有多种库可以用于解析 JSON 数据。以下介绍几个常用的库:

(一)Newtonsoft.Json(Json.NET)

  1. 简介:Json.NET 是一个流行的 .NET 库,提供了强大的 JSON 序列化和反序列化功能。它支持各种 .NET 语言,包括 Visual Basic。
  2. 安装
    • 可以通过 NuGet 包管理器来安装 Json.NET。在 Visual Studio 中,右键点击项目,选择“管理 NuGet 程序包”,在搜索框中输入“Newtonsoft.Json”,然后点击“安装”。
  3. 基本用法示例
Imports Newtonsoft.Json

Module Module1
    Sub Main()
        Dim json = "{ ""name"": ""John"", ""age"": 30, ""city"": ""New York"" }"
        Dim obj = JsonConvert.DeserializeObject(Of Dictionary(Of String, Object))(json)
        For Each kvp In obj
            Console.WriteLine(kvp.Key & ": " & kvp.Value)
        Next
    End Sub
End Module

在上述代码中,首先导入 Newtonsoft.Json 命名空间。然后定义一个 JSON 字符串,使用 JsonConvert.DeserializeObject 方法将 JSON 字符串反序列化为 Dictionary(Of String, Object) 类型的对象。最后通过遍历字典,输出键值对。

(二)Microsoft.Data.Json

  1. 简介:这是 Microsoft 提供的用于处理 JSON 数据的库,它提供了灵活的方式来读取、写入和查询 JSON 数据。
  2. 安装:同样可以通过 NuGet 包管理器安装。在 NuGet 包管理器中搜索“Microsoft.Data.Json”并安装。
  3. 基本用法示例
Imports Microsoft.Data.Json

Module Module1
    Sub Main()
        Dim jsonText = "{ ""name"": ""John"", ""age"": 30, ""city"": ""New York"" }"
        Dim jsonObject = JsonObject.Parse(jsonText)
        For Each property In jsonObject.Properties
            Console.WriteLine(property.Name & ": " & property.Value)
        Next
    End Sub
End Module

这里通过 JsonObject.Parse 方法将 JSON 字符串解析为 JsonObject 对象,然后遍历对象的属性并输出。

三、使用 Newtonsoft.Json 深入解析 JSON

(一)解析复杂 JSON 对象

当 JSON 数据包含嵌套的对象和数组时,Newtonsoft.Json 同样能轻松应对。

假设我们有如下复杂 JSON 数据:

{
    "name": "John",
    "age": 30,
    "address": {
        "street": "123 Main St",
        "city": "New York",
        "zip": "10001"
    },
    "hobbies": ["reading", "traveling"]
}

对应的 Visual Basic 解析代码如下:

Imports Newtonsoft.Json

Module Module1
    Class Address
        Public Property street As String
        Public Property city As String
        Public Property zip As String
    End Class

    Class Person
        Public Property name As String
        Public Property age As Integer
        Public Property address As Address
        Public Property hobbies As List(Of String)
    End Class

    Sub Main()
        Dim json = "{ ""name"": ""John"", ""age"": 30, ""address"": { ""street"": ""123 Main St"", ""city"": ""New York"", ""zip"": ""10001"" }, ""hobbies"": [""reading"", ""traveling""] }"
        Dim person = JsonConvert.DeserializeObject(Of Person)(json)
        Console.WriteLine("Name: " & person.name)
        Console.WriteLine("Age: " & person.age)
        Console.WriteLine("Street: " & person.address.street)
        Console.WriteLine("City: " & person.address.city)
        Console.WriteLine("Zip: " & person.address.zip)
        Console.WriteLine("Hobbies: " & String.Join(", ", person.hobbies))
    End Sub
End Module

在这段代码中,首先定义了 AddressPerson 两个类,用于匹配 JSON 数据的结构。Person 类包含 Address 类型的属性和字符串列表类型的 hobbies 属性。然后使用 JsonConvert.DeserializeObject 方法将 JSON 字符串反序列化为 Person 对象,并输出相关信息。

(二)处理 JSON 数组

如果 JSON 数据是一个数组,例如:

[
    {
        "name": "John",
        "age": 30
    },
    {
        "name": "Jane",
        "age": 25
    }
]

解析代码如下:

Imports Newtonsoft.Json

Module Module1
    Class Person
        Public Property name As String
        Public Property age As Integer
    End Class

    Sub Main()
        Dim json = "[ { ""name"": ""John"", ""age"": 30 }, { ""name"": ""Jane"", ""age"": 25 } ]"
        Dim people = JsonConvert.DeserializeObject(Of List(Of Person))(json)
        For Each person In people
            Console.WriteLine("Name: " & person.name & ", Age: " & person.age)
        Next
    End Sub
End Module

这里将 JSON 数组反序列化为 List(Of Person),然后遍历列表输出每个人的信息。

(三)自定义反序列化设置

Newtonsoft.Json 允许我们设置各种反序列化选项。例如,我们可以设置忽略 JSON 中不存在于目标类中的属性。

Imports Newtonsoft.Json

Module Module1
    Class Person
        Public Property name As String
        Public Property age As Integer
    End Class

    Sub Main()
        Dim json = "{ ""name"": ""John"", ""age"": 30, ""extraInfo"": ""Some extra data"" }"
        Dim settings = New JsonSerializerSettings()
        settings.MissingMemberHandling = MissingMemberHandling.Ignore
        Dim person = JsonConvert.DeserializeObject(Of Person)(json, settings)
        Console.WriteLine("Name: " & person.name)
        Console.WriteLine("Age: " & person.age)
    End Sub
End Module

在上述代码中,通过 JsonSerializerSettings 对象设置 MissingMemberHandlingMissingMemberHandling.Ignore,这样在反序列化时,如果 JSON 中有目标类不存在的属性(如 extraInfo),将被忽略。

四、使用 Microsoft.Data.Json 深入解析 JSON

(一)导航 JSON 对象结构

Microsoft.Data.Json 提供了一种导航式的方式来处理 JSON 对象。对于如下 JSON 数据:

{
    "name": "John",
    "age": 30,
    "address": {
        "street": "123 Main St",
        "city": "New York",
        "zip": "10001"
    }
}

解析代码如下:

Imports Microsoft.Data.Json

Module Module1
    Sub Main()
        Dim jsonText = "{ ""name"": ""John"", ""age"": 30, ""address"": { ""street"": ""123 Main St"", ""city"": ""New York"", ""zip"": ""10001"" } }"
        Dim jsonObject = JsonObject.Parse(jsonText)
        Console.WriteLine("Name: " & jsonObject.GetProperty("name").ValueAsString)
        Console.WriteLine("Age: " & jsonObject.GetProperty("age").ValueAsInt32)
        Dim addressObject = jsonObject.GetProperty("address").ValueAsObject
        Console.WriteLine("Street: " & addressObject.GetProperty("street").ValueAsString)
        Console.WriteLine("City: " & addressObject.GetProperty("city").ValueAsString)
        Console.WriteLine("Zip: " & addressObject.GetProperty("zip").ValueAsString)
    End Sub
End Module

在这段代码中,通过 JsonObject.Parse 方法将 JSON 字符串解析为 JsonObject 对象。然后使用 GetProperty 方法获取对象的属性,并根据属性值的类型使用相应的方法(如 ValueAsStringValueAsInt32 等)获取属性值。对于嵌套的 address 对象,先获取其 JsonObject,再继续获取内部属性值。

(二)处理 JSON 数组元素

当 JSON 数据包含数组时,如下:

[
    {
        "name": "John",
        "age": 30
    },
    {
        "name": "Jane",
        "age": 25
    }
]

解析代码如下:

Imports Microsoft.Data.Json

Module Module1
    Sub Main()
        Dim jsonText = "[ { ""name"": ""John"", ""age"": 30 }, { ""name"": ""Jane"", ""age"": 25 } ]"
        Dim jsonArray = JsonArray.Parse(jsonText)
        For Each item In jsonArray
            Dim obj = item.ValueAsObject
            Console.WriteLine("Name: " & obj.GetProperty("name").ValueAsString)
            Console.WriteLine("Age: " & obj.GetProperty("age").ValueAsInt32)
        Next
    End Sub
End Module

这里通过 JsonArray.Parse 方法将 JSON 数组字符串解析为 JsonArray 对象。然后遍历数组,将每个数组元素转换为 JsonObject,再获取并输出对象的属性值。

(三)动态查询 JSON 数据

Microsoft.Data.Json 还支持动态查询 JSON 数据。例如,我们想从如下 JSON 数据中获取所有年龄大于 25 的人的名字:

[
    {
        "name": "John",
        "age": 30
    },
    {
        "name": "Jane",
        "age": 25
    },
    {
        "name": "Bob",
        "age": 28
    }
]

代码如下:

Imports Microsoft.Data.Json

Module Module1
    Sub Main()
        Dim jsonText = "[ { ""name"": ""John"", ""age"": 30 }, { ""name"": ""Jane"", ""age"": 25 }, { ""name"": ""Bob"", ""age"": 28 } ]"
        Dim jsonArray = JsonArray.Parse(jsonText)
        For Each item In jsonArray
            Dim obj = item.ValueAsObject
            Dim age = obj.GetProperty("age").ValueAsInt32
            If age > 25 Then
                Console.WriteLine("Name: " & obj.GetProperty("name").ValueAsString)
            End If
        Next
    End Sub
End Module

在代码中,遍历 JSON 数组中的每个对象,获取 age 属性值并判断是否大于 25,如果满足条件则输出 name 属性值。

五、性能对比与选择建议

(一)性能对比

  1. Newtonsoft.Json:一般来说,Newtonsoft.Json 在序列化和反序列化复杂对象时表现出色,它采用了较为优化的算法。在处理大量数据和复杂对象结构时,其性能优势较为明显。例如,在将一个包含多层嵌套对象和大量数组元素的 JSON 数据反序列化为.NET 对象时,Newtonsoft.Json 的速度相对较快。
  2. Microsoft.Data.Json:Microsoft.Data.Json 在导航式处理 JSON 数据方面具有较好的性能。当需要快速定位和获取 JSON 对象中的特定属性值,尤其是在处理相对简单的 JSON 结构时,它的性能表现不错。但在处理复杂对象的整体反序列化时,性能可能稍逊于 Newtonsoft.Json。

(二)选择建议

  1. 如果项目对灵活性和复杂对象处理要求高:例如需要将 JSON 数据映射到复杂的.NET 对象模型,并且对序列化和反序列化的自定义设置有较多需求,建议选择 Newtonsoft.Json。它丰富的 API 和强大的功能可以满足各种复杂场景。
  2. 如果项目主要关注简单 JSON 数据的快速读取和导航:比如在一些轻量级的应用中,只需要从 JSON 数据中提取特定的几个属性值,Microsoft.Data.Json 是一个不错的选择。它的导航式操作方式简单直接,性能也能满足这类需求。
  3. 如果项目已经使用了大量的 Microsoft 官方库:为了保持一致性和更好的集成,选择 Microsoft.Data.Json 可能更合适。但如果项目对性能和通用性要求极高,即使已经使用了很多 Microsoft 库,Newtonsoft.Json 依然是一个值得考虑的强大工具。

六、错误处理与常见问题

(一)JSON 格式错误

  1. 错误原因:当 JSON 数据格式不正确时,如缺少引号、括号不匹配、属性名重复等,解析会失败。例如:
{
    "name: "John", // 这里属性名缺少引号
    "age": 30
}
  1. 处理方法:在使用解析库时,通常会抛出异常。在 Newtonsoft.Json 中,会抛出 Newtonsoft.Json.JsonReaderException 异常;在 Microsoft.Data.Json 中,会抛出 Microsoft.Data.Json.JsonParseException 异常。可以通过捕获这些异常来处理错误。例如,使用 Newtonsoft.Json 时:
Imports Newtonsoft.Json

Module Module1
    Sub Main()
        Try
            Dim json = "{ ""name: ""John"", ""age"": 30 }"
            Dim obj = JsonConvert.DeserializeObject(Of Dictionary(Of String, Object))(json)
        Catch ex As Newtonsoft.Json.JsonReaderException
            Console.WriteLine("JSON 格式错误: " & ex.Message)
        End Try
    End Sub
End Module

在捕获到异常后,可以根据异常信息提示用户 JSON 格式存在问题,并引导用户修正。

(二)类型不匹配问题

  1. 错误原因:当 JSON 数据中的值类型与目标对象的属性类型不匹配时,会出现类型不匹配问题。例如,将一个字符串类型的值赋给目标对象中期望是整数类型的属性。假设我们有如下 JSON 数据和目标类:
{
    "age": "thirty" // 这里 age 应该是整数类型,但给了字符串
}
Class Person
    Public Property age As Integer
End Class
  1. 处理方法:同样,解析库会抛出异常。在 Newtonsoft.Json 中,会抛出 Newtonsoft.Json.JsonSerializationException 异常;在 Microsoft.Data.Json 中,当使用特定的类型转换方法(如 ValueAsInt32 等)失败时也会抛出异常。我们可以通过捕获异常来处理。例如,使用 Newtonsoft.Json 时:
Imports Newtonsoft.Json

Module Module1
    Class Person
        Public Property age As Integer
    End Class

    Sub Main()
        Try
            Dim json = "{ ""age"": ""thirty"" }"
            Dim person = JsonConvert.DeserializeObject(Of Person)(json)
        Catch ex As Newtonsoft.Json.JsonSerializationException
            Console.WriteLine("类型不匹配错误: " & ex.Message)
        End Try
    End Sub
End Module

捕获异常后,可以提示用户数据类型存在问题,需要检查和修正 JSON 数据。

(三)属性不存在问题

  1. 错误原因:当在反序列化时,JSON 数据中缺少目标对象所需的属性,或者在使用导航式方法获取属性时,属性不存在,就会出现属性不存在问题。例如,目标类有一个 name 属性,但 JSON 数据中没有该属性:
{
    "age": 30
}
Class Person
    Public Property name As String
    Public Property age As Integer
End Class
  1. 处理方法:在 Newtonsoft.Json 中,可以通过设置 JsonSerializerSettingsMissingMemberHandling 属性来控制处理方式,如前面提到的设置为 MissingMemberHandling.Ignore 来忽略不存在的属性。在 Microsoft.Data.Json 中,当使用 GetProperty 方法获取不存在的属性时,会返回 Nothing,我们可以通过判断返回值来处理。例如:
Imports Microsoft.Data.Json

Module Module1
    Sub Main()
        Dim jsonText = "{ ""age"": 30 }"
        Dim jsonObject = JsonObject.Parse(jsonText)
        Dim nameProperty = jsonObject.GetProperty("name")
        If nameProperty IsNot Nothing Then
            Console.WriteLine("Name: " & nameProperty.ValueAsString)
        Else
            Console.WriteLine("Name 属性不存在")
        End If
    End Sub
End Module

通过这样的方式,可以避免在属性不存在时程序出现错误。

七、在实际项目中的应用场景

(一)Web 服务数据交互

在与 Web 服务进行数据交互时,很多 Web 服务以 JSON 格式返回数据。例如,调用一个天气预报的 Web API,它返回的天气信息可能是如下 JSON 格式:

{
    "city": "New York",
    "temperature": 25,
    "condition": "Sunny"
}

在 Visual Basic 客户端程序中,可以使用上述解析库将 JSON 数据解析为对象,方便在程序中使用。

Imports Newtonsoft.Json

Module Module1
    Class WeatherInfo
        Public Property city As String
        Public Property temperature As Integer
        Public Property condition As String
    End Class

    Sub Main()
        Dim json = "{ ""city"": ""New York"", ""temperature"": 25, ""condition"": ""Sunny"" }"
        Dim weather = JsonConvert.DeserializeObject(Of WeatherInfo)(json)
        Console.WriteLine("City: " & weather.city)
        Console.WriteLine("Temperature: " & weather.temperature)
        Console.WriteLine("Condition: " & weather.condition)
    End Sub
End Module

这样就可以轻松获取并展示天气信息。

(二)配置文件管理

将配置信息以 JSON 格式存储在配置文件中,程序启动时读取并解析。例如,一个数据库连接配置文件可能如下:

{
    "server": "localhost",
    "database": "myDB",
    "username": "admin",
    "password": "password123"
}

在 Visual Basic 程序中解析如下:

Imports Newtonsoft.Json

Module Module1
    Class DatabaseConfig
        Public Property server As String
        Public Property database As String
        Public Property username As String
        Public Property password As String
    End Class

    Sub Main()
        Dim json = "{ ""server"": ""localhost"", ""database"": ""myDB"", ""username"": ""admin"", ""password"": ""password123"" }"
        Dim config = JsonConvert.DeserializeObject(Of DatabaseConfig)(json)
        Console.WriteLine("Server: " & config.server)
        Console.WriteLine("Database: " & config.database)
        Console.WriteLine("Username: " & config.username)
        Console.WriteLine("Password: " & config.password)
    End Sub
End Module

通过这种方式,配置信息的管理更加灵活和易于维护。

(三)数据存储与传输优化

在一些应用中,需要将数据以 JSON 格式存储在文件中或在网络中传输。例如,在一个日志记录系统中,将日志信息以 JSON 格式存储,便于后续分析和处理。

[
    {
        "timestamp": "2023 - 10 - 01 12:00:00",
        "message": "User logged in",
        "user": "John"
    },
    {
        "timestamp": "2023 - 10 - 01 12:10:00",
        "message": "User created a new post",
        "user": "Jane"
    }
]

在 Visual Basic 程序中,可以将日志信息序列化为 JSON 格式并存储,读取时再解析。这样可以利用 JSON 的轻量级和跨平台特性,优化数据存储和传输。

八、总结与展望

在 Visual Basic 开发中,JSON 格式解析是一项重要的技能。通过掌握 Newtonsoft.Json 和 Microsoft.Data.Json 等库的使用,开发者可以轻松处理各种 JSON 数据,无论是简单的键值对还是复杂的嵌套结构。在实际项目中,合理选择解析库并正确处理解析过程中的错误,能够提高程序的稳定性和效率。

随着 JSON 在数据交换领域的持续广泛应用,未来可能会有更多优化和功能增强的 JSON 解析库出现。开发者需要关注最新的技术动态,不断提升自己处理 JSON 数据的能力,以更好地满足日益复杂的项目需求。同时,结合其他相关技术,如数据验证、加密等,能进一步提升 JSON 数据在应用中的安全性和可靠性。