# VBForums CodeBank > CodeBank - Visual Basic .NET >  JSON Parser

## minitech

Here's a JSON parser I created. To evaluate a JSON object, use New JSONObject(theJSONString). To retrieve a property, use JSONObject.GetProperty(name).



```
Imports System.Text.RegularExpressions

Public Class JSONObject

#Region "Shared Variables"
    Private Shared ReadOnly reProp As New Regex("(?<=(^|\,)\s*)([^\:]+)\s*\:\s*([^\,]+)", RegexOptions.Compiled)
    Private Shared ReadOnly reReplaced As New Regex("^\$\[\d+\]$", RegexOptions.Compiled)
#End Region

#Region "Shared Functions"

    Private Shared Function TokenizeJSON(ByVal json As String, ByVal l As List(Of String)) As String
        Dim r As String = String.Empty,
            nestable As String = "()[]{}",
            stringable As String = """'",
            nested As New Stack(Of Char),
            stringing As Char? = Nothing,
            start As Integer = -1
        l.Clear()

        For i As Integer = 0 To json.Length - 1
            Dim c As Char = json(i)
            If stringing IsNot Nothing Then
                If stringing = c Then
                    stringing = Nothing
                    If nested.Count = 0 Then
                        r &= "$[" & l.Count.ToString() & "]"
                        l.Add(json.Substring(start, i - start + 1))
                    End If
                End If
            ElseIf stringable.IndexOf(c) > -1 Then
                stringing = c
                If nested.Count = 0 Then start = i
            ElseIf nestable.IndexOf(c) Mod 2 = 0 Then
                If nested.Count = 0 Then start = i
                nested.Push(c)
            ElseIf nested.Count > 0 Then
                If nestable.IndexOf(nested.Peek()) + 1 = nestable.IndexOf(c) Then
                    nested.Pop()
                    If nested.Count = 0 Then
                        r &= "$[" & l.Count.ToString() & "]"
                        l.Add(json.Substring(start, i - start + 1))
                    End If
                End If
            Else
                r &= If(c = "\" OrElse c = "$", "\" & c, c)
            End If
        Next

        Return r
    End Function

    Private Shared Function ParseJSONObject(ByVal json As String) As Dictionary(Of String, String)
        Dim r As New Dictionary(Of String, String),
            l As New List(Of String)

        'Trim any leading or trailing object delimiters found in JSON objects.
        json = json.TrimStart("{"c, "("c, " "c).TrimEnd("}"c, ")"c, " "c)

        'Tokenize the JSON object.
        json = TokenizeJSON(json, l)

        'Parse the JSON object.
        For Each m As Match In reProp.Matches(json)
            Dim name As String = m.Groups(2).Value.TrimStart()
            Dim value As String = m.Groups(3).Value
            If reReplaced.IsMatch(name) Then name = l(Integer.Parse(name.Substring(2, name.Length - 3)))
            If reReplaced.IsMatch(value) Then value = l(Integer.Parse(value.Substring(2, value.Length - 3)))
            name = name.Trim("'"c, """"c)
            r.Add(name, value)
        Next

        'Return the result.
        Return r
    End Function

    Private Shared Function ParseJSONArray(ByVal json As String) As String()
        Dim l As New List(Of String),
            r As New List(Of String)

        'Trim any leading or trailing array delimiters found in JSON objects, but only one on each side.
        json = json.Trim()
        json = json.Substring(1, json.Length - 2)

        'Tokenize the JSON array.
        json = TokenizeJSON(json, l)

        'Parse and return the JSON array.
        For Each y As String In (From x As String In json.Split(","c) Select x.Trim())
            If reReplaced.IsMatch(y) Then
                r.Add(l(Integer.Parse(y.Substring(2, y.Length - 3))))
            Else
                r.Add(y)
            End If
        Next

        Return r.ToArray()
    End Function

#End Region

#Region "Variables"
    Private ReadOnly _properties As Dictionary(Of String, String)
#End Region

#Region "Constructor"
    Public Sub New(ByVal json As String)
        _properties = JSONObject.ParseJSONObject(json)
    End Sub
#End Region

#Region "Methods"
    Public Function GetProperty(ByVal name As String) As JSONValue
        If _properties.ContainsKey(name) Then Return Evaluate(_properties(name))

        Return New JSONValue(JSONType.undefined, Nothing)
    End Function

    Private Function Evaluate(ByVal json As String) As JSONValue
        Dim intValue As Integer,
            floatValue As Double
        json = json.TrimStart("("c).TrimEnd(")"c)

        If json <> String.Empty Then
            If json(0) = "{"c Then
                Return New JSONValue(JSONType.object, New JSONObject(json))
            ElseIf json(0) = "["c Then
                Return New JSONValue(JSONType.array, (From x As String In JSONObject.ParseJSONArray(json) Select Evaluate(x)).ToArray())
            ElseIf json(0) = "'"c OrElse json(0) = """"c Then
                Return New JSONValue(JSONType.string, json.Substring(1, json.Length - 2))
            ElseIf Integer.TryParse(json, intValue) Then
                Return New JSONValue(JSONType.int, intValue)
            ElseIf Double.TryParse(json, floatValue) Then
                Return New JSONValue(JSONType.double, floatValue)
            ElseIf json = "true" Then
                Return New JSONValue(JSONType.bool, True)
            ElseIf json = "false" Then
                Return New JSONValue(JSONType.bool, False)
            ElseIf json = "null" Then
                Return New JSONValue(JSONType.null, Nothing)
            End If
        End If

        Return New JSONValue(JSONType.undefined, Nothing)
    End Function
#End Region

End Class

Public Class JSONValue
    Private _type As JSONType,
            _value As Object

    Public Sub New(ByVal type As JSONType, ByVal value As Object)
        _type = type
        _value = value
    End Sub

    Public ReadOnly Property Type() As JSONType
        Get
            Return _type
        End Get
    End Property

    Public ReadOnly Property Value() As Object
        Get
            Return _value
        End Get
    End Property
End Class

Public Enum JSONType
    bool
    int
    [double]
    [string]
    [object]
    array
    null
    undefined
End Enum
```

----------


## bclarke47

The parsing mechanism works great, but, ran into a small issue when HTML is embedded within the JSON response.  The TokenizeJSON function is "breaking" on the doubled quote as it "thinks" the next double quote is the ending or the beginning of the next property/value.  Any thoughts you may would be very helpful.

Here is the JSON response with the HTML property...

"html":"<div class=\"info message-1507293770\">\n    <div class=\"sent\"><span>Sent:<\/span> Mon, 30 May<\/div>\n    <div class=\"from\"><span>From:<\/span> friday_night_8<\/div>\n    <div class=\"from\"><span>Subject:<\/span>\n                                heh?\n            <\/div>\n<\/div>\n<div class=\"message\">are you a vegetarian?<\/div>"

----------


## minitech

Hm... and yet the "stringable" and "stringing" variables should be there to counteract that! I haven't tested this extensively, but I will try to in the near future and I will attempt to fix the problem you describe.

----------


## weirddemon

> Hm... and yet the "stringable" and "stringing" variables should be there to counteract that! I haven't tested this extensively, but I will try to in the near future and I will attempt to fix the problem you describe.


Minitech,

I'm attempting to use your parser to grab some data from Reddit. I'm trying to grab the "about" data for a user and whenever I specify "kind", it works, but anything else also shows an empty string.

JSON:




> {"kind": "t2", "data": {"has_mail": false, "name": "weirddemon", "created": 1310935327.0, "modhash": "mavzqjcspta940d5218c7a971ec6865dcb886742adba6bf098", "created_utc": 1310935327.0, "link_karma": 1, "comment_karma": 0, "is_gold": false, "is_mod": false, "id": "5j1qm", "has_mod_mail": false}}


Code:


VB.NET Code:
MessageBox.Show(CStr(jsonParser.GetProperty("modhash").Value))

Any ideas?

----------


## minitech

The "modhash" property is a property of the "data" object, not the base JSON object. Your code should look something like this:


VB.NET Code:
MessageBox.Show(DirectCast(jsonParser.GetProperty("data").Value, JSONObject).GetProperty("modhash").Value.ToString())

----------


## weirddemon

> The "modhash" property is a property of the "data" object, not the base JSON object. Your code should look something like this:
> 
> 
> VB.NET Code:
> MessageBox.Show(DirectCast(jsonParser.GetProperty("data").Value, JSONObject).GetProperty("modhash").Value.ToString())


Oh, I gotcha. I'll have to play around with that then. That specific line throws an *Object reference not set to an instance of an object.* exception, probably when casting the JSONObject.

----------


## minitech

Hm. Sorry, I'm on a Mac away from home for the next few weeks, I can't debug... I'll try a complete rewrite sometime.

In the debugger, you can tell which expression resolves to Nothing, once you find that can you tell me so I can fix it?

Sorry about that...

----------


## Andrea Antonangeli

Minitech, your JSON parser is really nice.
How about using DynamicObject to make results more usable?

----------


## minitech

> Minitech, your JSON parser is really nice.
> How about using DynamicObject to make results more usable?


Good idea - I haven't touched this in a while. I'll do that now. Thanks  :Smilie:

----------


## wikidgh2

I know this thread is real old but can someone tell me why this doesn't work.

        Dim jsonParser As New JSONObject(Label14.Text)
        MessageBox.Show(DirectCast(jsonParser.GetProperty("data").Value, JSONObject).GetProperty("modhash").Value.ToString())




> {"kind": "t2", "data": {"has_mail": false, "name": "weirddemon", "created": 1310935327.0, "modhash": "mavzqjcspta940d5218c7a971ec6865dcb886742adba6bf098", "created_utc": 1310935327.0, "link_karma": 1, "comment_karma": 0, "is_gold": false, "is_mod": false, "id": "5j1qm", "has_mod_mail": false}}


is label14 text its a example someone posted in here but when I try it, it doesn't work

----------


## IAL32

Hi, i'm using this JSON string, but when i try to get the uri property, it gives me a NullReferenceException:

vbnet Code:
{"success":true,"payload":{"uid":"Gals","uri":"http://i.imm.io/Gals.png","link":"http://imm.io/Gals","name":"Capitolo1_1.PNG","format":"PNG","ext":"png","width":1279,"height":745,"size":"193 KB"}}

I'm using the following method:

vbnet Code:
DirectCast(jsonParser.GetProperty("payload").Value, JSONObject).GetProperty("uri").Value.ToString()
Regards,
IAL32

----------


## IAL32

Err...up?

----------


## robertvg

Hmm, I'm having the same issue if I want to get the geo coordinates of a twitter json string...: null reference exception :-(

----------


## minitech

Ah, I missed these. Sorry! I _could_ still work on this if anyone wants it (even just for some kind of reference), but there are some really good JSON libraries out there that already exist. Use those.

----------


## robertvg

which one would you recommend minitech ? (for VB.Net)

----------


## szlamany

Since I make JSON with this



```
        Dim sJson As String = ""
        Dim listJson As Dictionary(Of String, String) = New Dictionary(Of String, String)
.
.
        listJson.Add("docsize", allText.Length.ToString)
.
.
        sJson = New System.Web.Script.Serialization.JavaScriptSerializer().Serialize(listJson)
```

I assume you can find a deserialize method as well.

----------


## annunal

I like a lot the parser proposed below but I cannot parse this link

http://earthquake.usgs.gov/earthquak...00ij2v.geojson

in order to get

products...

it reads a lot of properties but skips this that this quite important.

Thanks

----------

