这个代码写的有点时间了,可能有点小bug,欢迎评论区反馈
作用是将Json文本转化成一个HarryNode类进行相关的Json对象处理或者读取,也可以将一个HarryNode对象用ToString变为Json文本。
举例:
1、读取节点数据
vbnet
dim harryNode = New HarryNode("", "{""msg"":""hello world!""}")
msgbox(harryNode.GetAtt("msg")) '弹窗显示hello world!
'下面展示更复杂的嵌套读取
dim harryNode = New HarryNode("", "{""node1"": {""msg"":""hello world!""}}")
msgbox(harryNode.GetAtt("node1.msg")) '弹窗显示hello world! 没错,用"."作为路径连接符进行寻址
'如果json的键里包含"."可以将源码里的"."替换成其它字符,也可以这样进行取值
msgbox(harryNode.GetAtt("node1")("msg").value
'这里的harryNode.GetAtt("node1")返回的是一个字典对象(String, HarryNode)
2、创建新Json节点,写入数据并输出文本
vbnet
Dim harryNode = New HarryNode("", "{}")
harryNode.SetAtt("msg", """hello world!""")
MsgBox(harryNode.ToString)
'可以看到SetAtt方法的第二个参数输入的字符串需要是json字符串格式,因此字符串本身需要加双引号
'下面可以用SetAtt的另一种重载方法,与上面代码的结果相同
harryNode.SetAtt("msg", "hello world!", NodeTypeEnum.isString)
MsgBox(harryNode.ToString)
'同样,对嵌套的复杂json对象,可以如下
harryNode.SetAtt("node1.msg", "hello world!", NodeTypeEnum.isString)
'下面这样写也是可以的
harryNode.SetAtt("node1", "{""msg"": ""hello world!""}")
文档
1、方法和函数
New
构造函数
|--------|-----------|--------------------|
| name | String | 节点的名字(对于根节点此项没啥意义) |
| json | String | 要解析构造的JSON串 |
| parent | HarryNode | 实例的父节点 |
|-----------|--------------|--------------------|
| name | String | 节点的名字(对于根节点此项没啥意义) |
| nodeValue | Object | 节点VB.NET对象值 |
| type | NodeTypeEnum | 节点值的类型 |
| parent | HarryNode | 实例的父节点 |
GetAtt
获得指定路径的VB.NET对象
|--------------|--------|---------------------|
| path | String | 节点路径 |
| defaultValue | Object | 没有获取到返回的值,默认Nothing |
SetAtt
根据指定路径设置节点值
|--------------|--------------|----------------|
| path | String | 节点路径 |
| newValue | Object | 节点的值(VB.NET对象) |
| newValueType | NodeTypeEnum | 值的类型 |
|------|--------|---------------|
| path | String | 节点路径 |
| json | String | 节点的值(JSON字符串) |
ReName
重命名某个节点
|---------|--------|------|
| path | String | 节点路径 |
| newName | String | 新名字 |
ToJson
返回JSON字符串,与ToString()等价
GetNode
获得指定路径的HarryNode对象
|------|--------|------|
| path | String | 节点路径 |
AddNode
添加子节点
|----------|--------|----------|
| path | String | 节点路径 |
| nodeName | String | 子节点名 |
| nodeJson | String | 子节点JSON串 |
Del
删除指定路径的节点
|------|--------|------|
| path | String | 节点路径 |
Merge
合并两个字典节点;
|------|-----------|--------|
| node | HarryNode | 要合并的节点 |
GetChildPath
返回一个当前节点子节点名的列表
Add
指定某个节点的数据加一个值
|----------|--------|------|
| path | String | 节点路径 |
| addValue | Single | 加数 |
ConAdd
指定某个节点的数据加一个值,但是限制了数的范围
|----------|--------|---------|
| path | String | 节点路径 |
| addValue | Single | 加数 |
| maxValue | Single | 最大值 |
| minValue | Single | 最小值,默认0 |
Mul
指定某个节点的数据乘一个值
|----------|--------|------|
| path | String | 节点路径 |
| addValue | Single | 乘数 |
Power
指定某个节点的数据求次幂
|----------|--------|------|
| path | String | 节点路径 |
| addValue | Single | 幂 |
2、属性
Value
当前节点的VB.NET类型值
3、事件
NodeContentChangeBefore
节点内容改变之前
|--------------|--------------|----------|
| path | String | 节点路径 |
| newValue | Object | 即将变成的值 |
| newValueType | NodeTypeEnum | 即将变成值的类型 |
NodeContentChangeBeforeFromJson
节点内容改变之前(通过JSON解释)
|------|--------|----------------|
| path | String | 节点路径 |
| json | String | 即将变成的值的JSON字符串 |
NodeContentChangeLater
节点内容改变之后
|--------------|--------------|--------|
| path | String | 节点路径 |
| newValue | Object | 变成的值 |
| newValueType | NodeTypeEnum | 变成值的类型 |
NodeContentChangeLaterFromJson
节点内容改变之后(通过JSON解释)
|------|--------|--------------|
| path | String | 节点路径 |
| json | String | 变成的值的JSON字符串 |
源码如下:
vbnet
Imports System.Text.RegularExpressions
Public Class HarryNode
Public Shared pathSeparator As String = "."
Public Shared outputFormat As Boolean = True
Public Shared formatRetraction As Integer = 2
Public Shared Function MulReplace(source As String, ParamArray args() As String) As String
If args.Length Mod 2 <> 0 Then
Return source
End If
For i As Integer = 0 To UBound(args) Step 2
source = Replace(source, args(i), args(i + 1))
Next
Return source
End Function
Public Shared Function ToEscape(source As String) As String
Return MulReplace(source, "\", "\\", vbCrLf, "\n", vbTab, "\t", """", "\""", Chr(8), "\b", Chr(12), "\f")
End Function
Public Enum NodeTypeEnum
isNull = 0
isString = 1
isSingle = 2
isDict = 3
isList = 4
isBool = 5
End Enum
Public nodeType As NodeTypeEnum
Public nodeName As String
Public parentNode As HarryNode
Private stringValue As String
Private singleValue As Single
Private boolValue As Boolean
Private childNode As Dictionary(Of String, HarryNode)
Public Event NodeContentChangeBefore(ByRef path As String, ByRef newValue As Object, ByRef newValueType As String)
Public Event NodeContentChangeBeforeFromJson(ByRef path As String, ByRef json As String)
Public Event NodeContentChangeLater(path As String, ByRef nowValue As Object, ByRef newValueType As NodeTypeEnum)
Public Event NodeContentChangeLaterFromJson(path As String, nowJson As String)
Public Sub Merge(node As HarryNode)
If nodeType = node.nodeType And nodeType = NodeTypeEnum.isDict Then
For i = 0 To node.childNode.Count - 1
Dim key = node.childNode.Keys(i)
If childNode.ContainsKey(key) Then
childNode(key).Merge(node.childNode(key))
Else
childNode.Add(key, node.childNode(key))
End If
Next
End If
End Sub
Public Function GetChildPath() As List(Of String)
Dim result As New List(Of String)
If nodeType = NodeTypeEnum.isDict Or nodeType = NodeTypeEnum.isList Then
result.AddRange(childNode.Keys)
Else
result.Add(nodeName)
End If
Return result
End Function
'Public Function GetTreeNode(interpreter As 解释器) As TreeNode
' Dim rootNode As New TreeNode(nodeName & interpreter.Search(nodeName))
' If nodeType = NodeTypeEnum.isDict Or nodeType = NodeTypeEnum.isList Then
' For Each cNode In childNode
' rootNode.Nodes.Add(cNode.Value.GetTreeNode(interpreter))
' Next
' Else
' rootNode.Nodes.Add(Value & interpreter.Search(Value))
' End If
' Return rootNode
'End Function
Public Sub Power(path As String, addValue As Single)
SetAtt(path, GetAtt(path, 0) ^ addValue, 0)
End Sub
Public Sub Add(path As String, addValue As Single)
SetAtt(path, GetAtt(path, 0) + addValue, 0)
End Sub
Public Sub ConAdd(path As String, addValue As Single, maxValue As Single, Optional minValue As Single = 0)
Dim newValue As Single = GetAtt(path, 0) + addValue
If newValue > maxValue Then
newValue = maxValue
End If
If newValue < minValue Then
newValue = minValue
End If
SetAtt(path, newValue, 0)
End Sub
Public Sub Mul(path As String, addValue As Single)
SetAtt(path, GetAtt(path, 0) * addValue, 0)
End Sub
Public Sub AddNode(path As String, nodeName As String, nodeJson As String)
Dim paths() As String = path.Split(pathSeparator)
Dim p As String
Dim node As HarryNode = Me
For i As Integer = 0 To UBound(paths) - 1
p = paths(i)
Select Case node.nodeType
Case NodeTypeEnum.isDict, NodeTypeEnum.isList
If node.nodeType = NodeTypeEnum.isList Then
p = Int(Val(p))
End If
If Not node.childNode.ContainsKey(p) Then
node.childNode.Add(p, New HarryNode(p, "{}", Me))
End If
Case Else
node.nodeType = NodeTypeEnum.isDict
node.childNode = New Dictionary(Of String, HarryNode)
If Not node.childNode.ContainsKey(p) Then
node.childNode.Add(p, New HarryNode(p, "{}", Me))
End If
End Select
node = node.childNode(p)
Next
p = paths.Last
Select Case node.nodeType
Case NodeTypeEnum.isDict, NodeTypeEnum.isList
If node.nodeType = NodeTypeEnum.isList Then
p = Int(Val(p))
End If
If Not node.childNode.ContainsKey(p) Then
node.childNode.Add(p, New HarryNode(p, "{}", Me))
End If
Case Else
node.nodeType = NodeTypeEnum.isDict
node.childNode = New Dictionary(Of String, HarryNode)
If Not node.childNode.ContainsKey(p) Then
node.childNode.Add(p, New HarryNode(p, "{}", Me))
End If
End Select
If Not node.childNode.ContainsKey(p) Then
node.childNode.Add(p, New HarryNode(nodeName, nodeJson, Me))
Else
node.childNode(p) = New HarryNode(nodeName, nodeJson, Me)
End If
End Sub
Public Sub Del(path As String)
Dim paths() As String = path.Split(pathSeparator)
Dim p As String
Dim node As HarryNode = Me
For i As Integer = 0 To UBound(paths) - 1
p = paths(i)
Select Case node.nodeType
Case NodeTypeEnum.isDict, NodeTypeEnum.isList
If node.nodeType = NodeTypeEnum.isList Then
p = Int(Val(p))
End If
If Not node.childNode.ContainsKey(p) Then
Return
End If
Case Else
node.nodeType = NodeTypeEnum.isDict
node.childNode = New Dictionary(Of String, HarryNode)
If Not node.childNode.ContainsKey(p) Then
Return
End If
End Select
node = node.childNode(p)
Next
p = paths.Last
Select Case node.nodeType
Case NodeTypeEnum.isDict, NodeTypeEnum.isList
If node.nodeType = NodeTypeEnum.isList Then
p = Int(Val(p))
End If
If Not node.childNode.ContainsKey(p) Then
Return
End If
Case Else
node.nodeType = NodeTypeEnum.isDict
node.childNode = New Dictionary(Of String, HarryNode)
If Not node.childNode.ContainsKey(p) Then
Return
End If
End Select
node.childNode.Remove(p)
End Sub
Public Function GetAtt(path As String, Optional defaultValue As Object = Nothing) As Object
If path = "" Then
Return Value
End If
Dim paths() As String = path.Split(pathSeparator)
Dim node As HarryNode = Me
For Each p As String In paths
Select Case node.nodeType
Case NodeTypeEnum.isDict, NodeTypeEnum.isList
If node.childNode.ContainsKey(p) Then
node = node.childNode(p)
Else
Return defaultValue
End If
Case Else
Return defaultValue
End Select
Next
Return node.Value
End Function
Public Function GetNode(path As String) As HarryNode
If path = "" Then
Return Me
End If
Dim p As String
Dim paths() As String = path.Split(pathSeparator)
Dim node As HarryNode = Me
For i As Integer = 0 To UBound(paths) - 1
p = paths(i)
Select Case node.nodeType
Case NodeTypeEnum.isDict, NodeTypeEnum.isList
If node.childNode.ContainsKey(p) Then
node = node.childNode(p)
Else
Return New HarryNode("", "", Me)
End If
Case Else
Return New HarryNode("", "", Me)
End Select
Next
If node.childNode IsNot Nothing AndAlso node.childNode.ContainsKey(paths.Last) Then
Return node.childNode(paths.Last)
End If
Return New HarryNode(paths.Last, String.Format("""{0}""", paths.Last), Me)
End Function
Public Sub SetAtt(path As String, newValue As Object, newValueType As String)
RaiseEvent NodeContentChangeBefore(path, newValue, newValueType)
Dim paths() As String = path.Split(pathSeparator)
Dim p As String
Dim node As HarryNode = Me
For i As Integer = 0 To UBound(paths) - 1
p = paths(i)
Select Case node.nodeType
Case NodeTypeEnum.isDict, NodeTypeEnum.isList
If node.nodeType = NodeTypeEnum.isList Then
p = Int(Val(p))
End If
If Not node.childNode.ContainsKey(p) Then
node.childNode.Add(p, New HarryNode(p, "{}", Me))
End If
Case Else
node.nodeType = NodeTypeEnum.isDict
node.childNode = New Dictionary(Of String, HarryNode)
If Not node.childNode.ContainsKey(p) Then
node.childNode.Add(p, New HarryNode(p, "{}", Me))
End If
End Select
node = node.childNode(p)
Next
p = paths.Last
Select Case node.nodeType
Case NodeTypeEnum.isDict, NodeTypeEnum.isList
If node.nodeType = NodeTypeEnum.isList Then
p = Int(Val(p))
End If
If Not node.childNode.ContainsKey(p) Then
node.childNode.Add(p, New HarryNode(p, newValue, newValueType, Me))
End If
Case Else
node.nodeType = NodeTypeEnum.isDict
node.childNode = New Dictionary(Of String, HarryNode)
If Not node.childNode.ContainsKey(p) Then
node.childNode.Add(p, New HarryNode(p, newValue, newValueType, Me))
End If
End Select
node.childNode(p).Value = newValue
RaiseEvent NodeContentChangeLater(path, node.childNode(p).Value, node.nodeType)
End Sub
Public Sub ReName(path As String, newName As String)
Dim paths() As String = path.Split(pathSeparator)
Dim p As String
Dim node As HarryNode = Me
For i As Integer = 0 To UBound(paths) - 1
p = paths(i)
Select Case node.nodeType
Case NodeTypeEnum.isDict, NodeTypeEnum.isList
If node.nodeType = NodeTypeEnum.isList Then
p = Int(Val(p))
End If
If Not node.childNode.ContainsKey(p) Then
node.childNode.Add(p, New HarryNode(p, "{}", Me))
End If
Case Else
node.nodeType = NodeTypeEnum.isDict
node.childNode = New Dictionary(Of String, HarryNode)
If Not node.childNode.ContainsKey(p) Then
node.childNode.Add(p, New HarryNode(p, "{}", Me))
End If
End Select
node = node.childNode(p)
Next
p = paths.Last
Select Case node.nodeType
Case NodeTypeEnum.isDict, NodeTypeEnum.isList
If node.nodeType = NodeTypeEnum.isList Then
p = Int(Val(p))
End If
If node.childNode.ContainsKey(p) Then
' 修改
node.childNode.Add(newName, New HarryNode(newName, node.childNode(p).ToJson, Me))
node.childNode.Remove(p)
End If
Case Else
node.nodeType = NodeTypeEnum.isDict
node.childNode = New Dictionary(Of String, HarryNode)
If node.childNode.ContainsKey(p) Then
node.childNode.Add(newName, New HarryNode(newName, node.childNode(p).ToJson, Me))
node.childNode.Remove(p)
End If
End Select
End Sub
Public Sub SetAtt(path As String, json As String)
RaiseEvent NodeContentChangeBeforeFromJson(path, json)
Dim paths() As String = path.Split(pathSeparator)
Dim p As String
Dim node As HarryNode = Me
For i As Integer = 0 To UBound(paths) - 1
p = paths(i)
Select Case node.nodeType
Case NodeTypeEnum.isDict, NodeTypeEnum.isList
If node.nodeType = NodeTypeEnum.isList Then
p = Int(Val(p))
End If
If Not node.childNode.ContainsKey(p) Then
node.childNode.Add(p, New HarryNode(p, "{}", Me))
End If
Case Else
node.nodeType = NodeTypeEnum.isDict
node.childNode = New Dictionary(Of String, HarryNode)
If Not node.childNode.ContainsKey(p) Then
node.childNode.Add(p, New HarryNode(p, "{}", Me))
End If
End Select
node = node.childNode(p)
Next
p = paths.Last
Select Case node.nodeType
Case NodeTypeEnum.isDict, NodeTypeEnum.isList
If node.nodeType = NodeTypeEnum.isList Then
p = Int(Val(p))
End If
If Not node.childNode.ContainsKey(p) Then
node.childNode.Add(p, New HarryNode(p, "{}", Me))
End If
Case Else
node.nodeType = NodeTypeEnum.isDict
node.childNode = New Dictionary(Of String, HarryNode)
If Not node.childNode.ContainsKey(p) Then
node.childNode.Add(p, New HarryNode(p, "{}", Me))
End If
End Select
node.childNode(p).JsonToValue(json)
RaiseEvent NodeContentChangeLaterFromJson(path, json)
End Sub
Public Function ToJson(Optional deep As Integer = 1) As String
If outputFormat Then
Dim deepFormatRetraction = New String(" ", deep * formatRetraction)
Dim deepFormatRetractionSub1 = New String(" ", (deep - 1) * formatRetraction)
Select Case nodeType
Case NodeTypeEnum.isString
Return String.Format("""{0}""", ToEscape(stringValue))
Case NodeTypeEnum.isBool
Return boolValue.ToString.ToLower
Case NodeTypeEnum.isSingle
Return singleValue
Case NodeTypeEnum.isDict
Dim result As New List(Of String)
For i As Integer = 0 To childNode.Count - 1
result.Add(String.Format(deepFormatRetraction & """{0}"": {1}", childNode.Keys(i), childNode.Values(i).ToJson(deep + 1)))
Next
Return String.Format(Replace("{{\n{0}\n{1}}}", "\n", vbCrLf), Join(result.ToArray, "," & vbCrLf), deepFormatRetractionSub1)
Case NodeTypeEnum.isList
Dim result As New List(Of String)
For i As Integer = 0 To childNode.Count - 1
result.Add(deepFormatRetraction & childNode.Values(i).ToJson(deep + 1))
Next
Return String.Format(Replace("[\n{0}\n{1}]", "\n", vbCrLf), Join(result.ToArray, "," & vbCrLf), deepFormatRetractionSub1)
Case Else
Return ""
End Select
End If
Select Case nodeType
Case NodeTypeEnum.isString
Return String.Format("""{0}""", ToEscape(stringValue))
Case NodeTypeEnum.isBool
Return boolValue
Case NodeTypeEnum.isSingle
Return singleValue
Case NodeTypeEnum.isDict
Dim result As New List(Of String)
For i As Integer = 0 To childNode.Count - 1
result.Add(String.Format("""{0}"":{1}", childNode.Keys(i), childNode.Values(i).ToJson))
Next
Return String.Format("{{{0}}}", Join(result.ToArray, ","))
Case NodeTypeEnum.isList
Dim result As New List(Of String)
For i As Integer = 0 To childNode.Count - 1
result.Add(childNode.Values(i).ToJson)
Next
Return String.Format("[{0}]", Join(result.ToArray, ","))
Case Else
Return ""
End Select
End Function
Public Overloads Function ToString() As String
Return ToJson()
End Function
Public Property Value() As Object
Get
Select Case nodeType
Case NodeTypeEnum.isString
Return stringValue
Case NodeTypeEnum.isBool
Return boolValue
Case NodeTypeEnum.isSingle
Return singleValue
Case NodeTypeEnum.isDict
Return childNode
Case NodeTypeEnum.isList
Return childNode.Values
Case Else
Return Nothing
End Select
End Get
Set(value As Object)
Select Case nodeType
Case NodeTypeEnum.isString
stringValue = value
Case NodeTypeEnum.isBool
boolValue = value
Case NodeTypeEnum.isSingle
singleValue = value
Case NodeTypeEnum.isDict
childNode = value
Case NodeTypeEnum.isList
Dim valueList As List(Of HarryNode) = value
childNode.Clear()
For i As Integer = 0 To valueList.Count - 1
childNode.Add(i, valueList(i))
Next
End Select
End Set
End Property
Public Sub JsonToValue(json As String)
If json Is Nothing Then
Return
End If
json = Regex.Match(json, "^\s*(.*?)\s*$", RegexOptions.Singleline).Groups(1).Value
If Regex.IsMatch(json, "^"".*""$", RegexOptions.Singleline) Then
'字符串
nodeType = NodeTypeEnum.isString
stringValue = json.Substring(1, json.Length - 2)
ElseIf Regex.IsMatch(json, "^{.*}$", RegexOptions.Singleline) Then
'字典
nodeType = NodeTypeEnum.isDict
If json = "{}" OrElse Regex.IsMatch(json, "^\s*\{\s*\}\s*$") Then
childNode = New Dictionary(Of String, HarryNode)
Else
childNode = GetDict(json, Me)
End If
ElseIf Regex.IsMatch(json, "^\[.*\]$", RegexOptions.Singleline) Then
'列表
nodeType = NodeTypeEnum.isList
If json = "[]" OrElse Regex.IsMatch(json, "^\s*\[\s*\]\s*$") Then
childNode = New Dictionary(Of String, HarryNode)
Else
childNode = GetList(json, Me)
End If
ElseIf Regex.IsMatch(json, "^[-]{0,1}[\d]*[\.]{0,1}[\d]*$", RegexOptions.Singleline) Then
'数值
nodeType = NodeTypeEnum.isSingle
singleValue = Val(json)
Else
'布尔值
nodeType = NodeTypeEnum.isBool
boolValue = GetBool(json)
End If
End Sub
Public Shared Function GetDict(json As String, sourceNode As HarryNode) As Dictionary(Of String, HarryNode)
'Debug.WriteLine(String.Format("GetDict.json={0}", json))
Dim node As New Dictionary(Of String, HarryNode)
Dim name As String = ""
Dim temp As New List(Of String)
Dim bigBrackets As Integer
Dim colon As Integer
Dim doubleQuotationMark As Integer
Dim brackets As Integer
Dim escape As Integer
Dim stringContent As String
Dim exegesis As Integer
For Each c As String In json
'Debug.WriteLine(Join(temp.ToArray, ""))
'Debug.WriteLine("doubleQuotationMark={0}", doubleQuotationMark)
'Debug.WriteLine("exegesis={0}", exegesis)
'Debug.WriteLine("bigBrackets={0}", bigBrackets)
'Debug.WriteLine("brackets={0}", brackets)
'Debug.WriteLine("")
If c = "/" Then
exegesis += 1
Continue For
ElseIf exegesis = 1 Then
temp.Add("/")
exegesis = 0
End If
If exegesis >= 2 Then
If c = vbCr Or c = vbLf Then
exegesis = 0
Else
Continue For
End If
End If
If doubleQuotationMark = 0 Then
'未在字符串内时
Select Case c
Case "{"
bigBrackets += 1
If bigBrackets > 1 OrElse brackets > 0 Then
'子嵌套记忆
temp.Add(c)
End If
Case "}"
bigBrackets -= 1
If bigBrackets > 1 OrElse brackets > 0 OrElse (bigBrackets = 1 AndAlso brackets = 0) Then
temp.Add(c)
End If
Case "["
brackets += 1
temp.Add(c)
Case "]"
brackets -= 1
temp.Add(c)
Case ":"
If bigBrackets = 1 AndAlso brackets = 0 Then
'第一层嵌套内
colon += 1
ElseIf bigBrackets > 1 OrElse brackets > 0 Then
temp.Add(c)
End If
Case """"
If bigBrackets = 1 AndAlso brackets = 0 Then
'第一层嵌套内
doubleQuotationMark += 1
temp.Add(c)
ElseIf bigBrackets > 1 OrElse brackets > 0 Then
temp.Add(c)
End If
Case ","
If colon > 0 AndAlso bigBrackets = 1 AndAlso brackets = 0 Then
'非字符串
If temp.Count > 0 Then
stringContent = Join(temp.ToArray, "")
temp.Clear()
node.Add(name, New HarryNode(name, stringContent, sourceNode))
Else
'null
node.Add(name, New HarryNode(name, Nothing, sourceNode))
End If
colon = 0
Else
temp.Add(c)
End If
Case Else
If bigBrackets > 1 Or Regex.IsMatch(c, "\S", RegexOptions.Singleline) Then
temp.Add(c)
End If
End Select
ElseIf bigBrackets = 1 AndAlso brackets = 0 Then
'第一层嵌套内
'在字符串内
Select Case c
Case """"
temp.Add(c)
If escape = 1 Then
'转义"
escape = 0
Else
doubleQuotationMark = 0
If colon = 0 Then
'节点名
stringContent = Join(temp.ToArray, "")
temp.Clear()
name = stringContent.Substring(1, stringContent.Length - 2)
End If
End If
Case "\"
escape += 1
If escape > 1 Then
'转义\
temp.Add(c)
escape = 0
End If
Case "n"
If escape = 1 Then
'转义换行
temp.Add(vbCrLf)
escape = 0
Else
temp.Add(c)
End If
Case "b"
If escape = 1 Then
temp.Add(Chr(8))
escape = 0
Else
temp.Add(c)
End If
Case "f"
If escape = 1 Then
temp.Add(Chr(12))
escape = 0
Else
temp.Add(c)
End If
Case "t"
If escape = 1 Then
temp.Add(vbTab)
escape = 0
Else
temp.Add(c)
End If
Case Else
escape = 0
temp.Add(c)
End Select
End If
Next
If temp.Count > 0 Then
stringContent = Join(temp.ToArray, "")
temp.Clear()
node.Add(name, New HarryNode(name, stringContent, sourceNode))
Else
'null
node.Add(name, New HarryNode(name, Nothing, sourceNode))
End If
Return node
End Function
Public Shared Function GetList(json As String, sourceNode As HarryNode) As Dictionary(Of String, HarryNode)
'Debug.WriteLine(String.Format("GetList.json={0}", json))
Dim node As New Dictionary(Of String, HarryNode)
Dim name As String
Dim temp As New List(Of String)
Dim bigBrackets As Integer
Dim doubleQuotationMark As Integer
Dim brackets As Integer
Dim escape As Integer
Dim comma As Integer
Dim stringContent As String
For Each c As String In json
Dim exegesis As Integer
If c = "/" Then
exegesis += 1
Continue For
ElseIf exegesis = 1 Then
temp.Add("/")
exegesis = 0
End If
If exegesis >= 2 Then
If c = vbCr Or c = vbLf Then
exegesis = 0
Else
Continue For
End If
End If
If doubleQuotationMark = 0 Then
'未在字符串内时
Select Case c
Case "["
brackets += 1
If brackets > 1 OrElse bigBrackets > 0 Then
'子嵌套记忆
temp.Add(c)
End If
Case "]"
brackets -= 1
If brackets > 1 OrElse bigBrackets > 0 OrElse (brackets = 1 AndAlso bigBrackets = 0) Then
temp.Add(c)
End If
Case "{"
bigBrackets += 1
temp.Add(c)
Case "}"
bigBrackets -= 1
temp.Add(c)
Case """"
If brackets = 1 AndAlso bigBrackets = 0 Then
'第一层嵌套内
doubleQuotationMark += 1
temp.Add(c)
ElseIf brackets > 1 OrElse bigBrackets > 0 Then
temp.Add(c)
End If
Case ","
If bigBrackets = 0 AndAlso brackets = 1 Then
name = comma
comma += 1
If temp.Count > 0 Then
stringContent = Join(temp.ToArray, "")
temp.Clear()
node.Add(name, New HarryNode(name, stringContent, sourceNode))
Else
'null
node.Add(name, New HarryNode(name, Nothing, sourceNode))
End If
Else
temp.Add(c)
End If
Case Else
If bigBrackets > 1 Or Regex.IsMatch(c, "\S", RegexOptions.Singleline) Then
temp.Add(c)
End If
End Select
ElseIf brackets = 1 AndAlso bigBrackets = 0 Then
'第一层嵌套内
'在字符串内
Select Case c
Case """"
temp.Add(c)
If escape = 1 Then
'转义"
escape = 0
Else
doubleQuotationMark = 0
End If
Case "\"
escape += 1
If escape > 1 Then
'转义\
temp.Add(c)
escape = 0
End If
Case "n"
If escape = 1 Then
'转义换行
temp.Add(vbCrLf)
escape = 0
Else
temp.Add(c)
End If
Case "b"
If escape = 1 Then
temp.Add(Chr(8))
escape = 0
Else
temp.Add(c)
End If
Case "f"
If escape = 1 Then
temp.Add(Chr(12))
escape = 0
Else
temp.Add(c)
End If
Case "t"
If escape = 1 Then
temp.Add(vbTab)
escape = 0
Else
temp.Add(c)
End If
Case Else
escape = 0
temp.Add(c)
End Select
End If
Next
name = comma
If temp.Count > 0 Then
'非字符串
stringContent = Join(temp.ToArray, "")
temp.Clear()
node.Add(name, New HarryNode(name, stringContent, sourceNode))
Else
'null
node.Add(name, New HarryNode(name, Nothing, sourceNode))
End If
Return node
End Function
Public Shared Function GetBool(value As String) As Boolean
If value.ToLower = "false" OrElse value = "0" Then
Return False
End If
Return True
End Function
Public Sub New(name As String, json As String, Optional parent As HarryNode = Nothing)
nodeName = name
parentNode = parent
JsonToValue(json)
End Sub
Public Sub New(name As String, nodeValue As Object, type As NodeTypeEnum, Optional parent As HarryNode = Nothing)
nodeName = name
nodeType = type
parentNode = parent
Value = nodeValue
End Sub
End Class