You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Wonderware ArchestrA/Quickscript.NET中反序列化JSON的标准最佳方法

JSON反序列化在QuickScript.NET(Wonderware ArchestrA IDE)中的可行方案

我之前在ArchestrA IDE的QuickScript.NET环境里遇到过完全一样的问题——常用的JSON处理类(JavaScriptSerializer、DataContractJsonSerializer甚至Newtonsoft.Json)要么找不到对应的命名空间,要么直接不可用。结合这个环境的限制,我整理了几个实用的解决办法:

1. 手动解析(适合简单JSON结构)

如果你的JSON格式比较固定且不复杂(比如只有扁平的键值对,没有嵌套对象/数组),直接用字符串操作提取值是最直接的方式,不需要依赖任何额外类。

举个例子,解析如下JSON:

{"DeviceName":"Pump_01","Pressure":85.6,"IsRunning":true}

对应的QuickScript.NET代码(VB.NET):

Dim rawJson As String = "{""DeviceName"":""Pump_01"",""Pressure"":85.6,""IsRunning"":true}"

' 提取DeviceName字符串
Dim nameStart = rawJson.IndexOf("""DeviceName"":""") + 14
Dim nameEnd = rawJson.IndexOf("""", nameStart)
Dim deviceName As String = rawJson.Substring(nameStart, nameEnd - nameStart)

' 提取Pressure数值
Dim pressureStart = rawJson.IndexOf("""Pressure"":") + 11
Dim pressureEnd = rawJson.IndexOf(",", pressureStart)
Dim pressure As Double = Double.Parse(rawJson.Substring(pressureStart, pressureEnd - pressureStart))

' 提取IsRunning布尔值
Dim runningStart = rawJson.IndexOf("""IsRunning"":") + 13
Dim runningEnd = rawJson.IndexOf("}", runningStart)
Dim isRunning As Boolean = Boolean.Parse(rawJson.Substring(runningStart, runningEnd - runningStart))

这种方法的缺点是灵活性差,一旦JSON结构变化就得修改代码,但胜在简单直接,没有任何依赖。

2. 使用正则表达式解析(适合中等复杂度结构)

如果JSON有少量嵌套或者字段较多,可以用System.Text.RegularExpressions(这个命名空间在QuickScript.NET里是可用的)来匹配键值对,比纯手动字符串操作更灵活。

示例代码:

Imports System.Text.RegularExpressions

Dim rawJson As String = "{""DeviceName"":""Pump_01"",""Pressure"":85.6,""IsRunning"":true,""Tags"":[""Flow"",""Level""]}"

' 匹配字符串类型的键值对
Dim stringMatches As MatchCollection = Regex.Matches(rawJson, """(\w+)"":""([^""]+)""")
For Each match As Match In stringMatches
    Dim key As String = match.Groups(1).Value
    Dim value As String = match.Groups(2).Value
    ' 处理字符串值,比如打印或存储
    ' Console.WriteLine($"{key}: {value}")
Next

' 匹配数字/布尔类型的键值对
Dim numBoolMatches As MatchCollection = Regex.Matches(rawJson, """(\w+)"":([\d\.truefalse]+)")
For Each match As Match In numBoolMatches
    Dim key As String = match.Groups(1).Value
    Dim valueStr As String = match.Groups(2).Value
    
    Select Case valueStr.ToLower()
        Case "true", "false"
            Dim boolVal As Boolean = Boolean.Parse(valueStr)
            ' 处理布尔值
        Case Else
            If valueStr.Contains(".") Then
                Dim doubleVal As Double = Double.Parse(valueStr)
                ' 处理浮点数
            Else
                Dim intVal As Integer = Integer.Parse(valueStr)
                ' 处理整数
            End If
    End Select
Next

' 匹配简单数组(比如字符串数组)
Dim arrayMatches As Match = Regex.Match(rawJson, """Tags"":\[([^\]]+)\]")
If arrayMatches.Success Then
    Dim arrayItems As String() = arrayMatches.Groups(1).Value.Replace("""", "").Split(","c)
    ' 遍历数组元素
    For Each item As String In arrayItems
        ' 处理数组项
    Next
End If

正则方法能覆盖大部分常见的JSON结构,但对于深度嵌套的复杂JSON(比如多层对象嵌套),正则会变得难以维护。

3. 嵌入轻量级JSON解析器(适合复杂JSON结构)

如果你的JSON结构复杂(多层嵌套对象、数组混合),前面两种方法就不太适用了。这时候可以找一个无外部依赖、纯VB.NET编写的轻量级JSON解析器,把它的代码直接复制到你的QuickScript.NET脚本中。

这类解析器通常是单文件的类,只依赖.NET基础类库(比如System.Collections.Generic),而这些在QuickScript.NET里都是可用的。你可以自己实现一个简单的解析器,或者找公开的开源代码(比如一些精简版的JSON解析器,不需要引用任何DLL)。

比如一个极简的解析器核心逻辑示例(你需要补充完整的辅助方法):

Imports System.Collections.Generic

Public Class MiniJsonParser
    Private Shared Sub SkipWhitespace(ByVal json As String, ByRef index As Integer)
        While index < json.Length AndAlso Char.IsWhiteSpace(json(index))
            index += 1
        End While
    End Sub

    Private Shared Function ParseString(ByVal json As String, ByRef index As Integer) As String
        index += 1 ' 跳过开头的引号
        Dim start = index
        While index < json.Length AndAlso json(index) <> """"c
            If json(index) = "\"c Then index += 1 ' 处理转义字符
            index += 1
        End While
        Dim result = json.Substring(start, index - start)
        index += 1 ' 跳过结尾的引号
        Return result
    End Function

    Private Shared Function ParseObject(ByVal json As String, ByRef index As Integer) As Dictionary(Of String, Object)
        index += 1 ' 跳过开头的{
        Dim dict As New Dictionary(Of String, Object)()
        SkipWhitespace(json, index)
        While index < json.Length AndAlso json(index) <> "}"c
            Dim key = ParseString(json, index)
            SkipWhitespace(json, index)
            index += 1 ' 跳过冒号
            Dim value = ParseValue(json, index)
            dict.Add(key, value)
            SkipWhitespace(json, index)
            If json(index) = ","c Then index += 1
            SkipWhitespace(json, index)
        End While
        index += 1 ' 跳过结尾的}
        Return dict
    End Function

    ' 补充ParseValue、ParseArray、ParseBoolean、ParseNull、ParseNumber等方法
    Private Shared Function ParseValue(ByVal json As String, ByRef index As Integer) As Object
        SkipWhitespace(json, index)
        Select Case json(index)
            Case """"c : Return ParseString(json, index)
            Case "{"c : Return ParseObject(json, index)
            Case "["c : Return ParseArray(json, index) ' 需要实现ParseArray
            Case "t"c : Return ParseBoolean(json, index) ' 需要实现ParseBoolean
            Case "f"c : Return ParseBoolean(json, index)
            Case "n"c : Return ParseNull(json, index) ' 需要实现ParseNull
            Case Else : Return ParseNumber(json, index) ' 需要实现ParseNumber
        End Select
    End Function
End Class

把完整的解析器代码嵌入后,你就可以像使用常规JSON库一样解析复杂JSON了:

Dim rawJson As String = "{""Device"":{""Name"":""Pump_01"",""Sensors"":[{""Type"":""Pressure"",""Value"":85.6},{""Type"":""Flow"",""Value"":12.3}]}}"
Dim jsonObj As Dictionary(Of String, Object) = MiniJsonParser.ParseObject(rawJson, 0)
' 访问嵌套对象
Dim deviceName As String = DirectCast(jsonObj("Device"), Dictionary(Of String, Object))("Name")

这个方案的优势是能处理任意复杂的JSON结构,缺点是需要引入额外的代码,但因为是直接嵌入脚本,不需要依赖外部DLL,完全符合QuickScript.NET的环境限制。


内容的提问来源于stack exchange,提问作者mijiturka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:31:37