A Visual Basic .NET JSON transformer that converts a JSON literal into a strongly structured XML (XDocument) representation.
This project provides a custom JSON lexer and recursive-descent parser, producing a 1-to-1, lossless XML representation of JSON values, objects, and arrays.
- Written in VB.NET
- Targets .NET Standard 2.0 (usable from .NET Framework, .NET Core, .NET 5+)
- Fully custom JSON lexer + parser (no external JSON libraries)
- Produces safe, schema-stable XML
- Supports:
- Strings (including all escape sequences)
- Numbers (culture-aware or custom numeric formats)
- Booleans
- Null
- Arrays
- Objects
- Extensive unit test coverage (test project targets .NET 10)
This version is a complete rewrite of the original implementation.
- Architecture rewrite
- Old monolithic parser replaced with:
- JsonLexer (tokenization)
- JsonParser (grammar enforcement)
- JsonTransformer (public API)
- Old monolithic parser replaced with:
- Boolean values are semantic
- Booleans are now emitted as real boolean values, not string literals.
- Whitespace handling
- Leading whitespace is preserved for accurate error positions.
The transformer is built as a .NET Standard 2.0 class library and included in the v2.0 release: v2.0
- Right-click your project in the Solution Explorer
- Add Project Reference
- Go to the Browse tab
- Click on the Browse... button
- Select the DLL
- Click on the OK button
The transformer is built as a .NET Standard 2.0 class library.
- Build the project
- Reference the compiled DLL from your project
- Import the namespace:
Imports JsonThis works from:
- .NET Framework
- .NET Core
- .NET 5+
If you prefer source inclusion:
- Copy the following files into your project:
- JsonLexer.vb
- JsonParser.vb
- JsonTransformer.vb
- All the custom exception and token class files
- Ensure your project references:
Microsoft.VisualBasicSystem.GlobalizationSystem.Collections.GenericSystem.LinqSystem.TextSystem.Xml.Linq
Namespace: Json Creates a new XDocument from a JSON literal
| Name | Description |
|---|---|
| Parse(String) | Creates a new XDocument from a JSON literal using the official JSON EBNF for parsing numbers. |
| Parse(String, CultureInfo) | Creates a new XDocument from a JSON literal using culture specific characters for parsing numbers. |
| Parse(String, String, String, String) | Creates a new XDocument from a JSON literal using custom values for parsing numbers. |
Using one of the overloads of this method, you can transform a JSON literal into an XDocument while optionally specifying how number parsing should be handled.
Creates a new XDocument from a JSON literal using the official JSON EBNF for parsing numbers.
Public Shared Function Parse(source As String) As XDocumentsource String
The JSON literal to be transformed.
XDocument An XDocument object that contains the transformed JSON data.
This overload follows the EBNF defined in JSON.org with the following deviations:
- Booleans
- Case-insensitive (
true,TRUE,True, etc.)
- Case-insensitive (
- Null
- Case-insensitive (
null,NULL)
- Case-insensitive (
Dim literal = "{ ""Property1"": 1, ""Property2"": false }"
Dim document As XDocument = JsonTransformer.Parse(literal)
Debug.WriteLine(document.ToString())Creates a new XDocument from a JSON literal using culture specific characters for parsing numbers.
Public Shared Function Parse(source As String, culture As CultureInfo) As XDocumentsource String
The JSON literal to be transformed.
culture CultureInfo
The culture to use when parsing numbers.
XDocument An XDocument object that contains the transformed JSON data.
This overload follows the EBNF defined in JSON.org with the following deviations:
- Numbers
- Unary positive sign supported at beginning of numbers
- Decimal place derived from:
- Unary positive and negative signs derived from:
- Booleans
- Case-insensitive (
true,TRUE,True, etc.)
- Case-insensitive (
- Null
- Case-insensitive (
null,NULL)
- Case-insensitive (
Dim literal = "123,45"
Dim culture As New Globalization.CultureInfo("de-DE")
Dim document As XDocument = JsonTransformer.Parse(literal, culture)
Debug.WriteLine(document.ToString())Creates a new XDocument from a JSON literal using custom values for parsing numbers.
Public Shared Function Parse(source As String, Optional decimalSeparator As String = DEFAULT_DECIMAL_SEPARATOR, Optional negativeSign As String = DEFAULT_UNARY_NEGATIVE_OPERATOR, Optional positiveSign As String = DEFAULT_UNARY_POSITIVE_OPERATOR) As XDocumentsource String
The JSON literal to be transformed.
decimalSeparator String (optional)
The custom decimal separator to be used.
negativeSign String (optional)
The negative sign character to be used
positiveSign String (optional)
The positive sign character to be used
XDocument An XDocument object that contains the transformed JSON data.
This overload follows the EBNF defined in JSON.org with the following deviations:
- Numbers
- Unary positive sign supported at beginning of numbers
- If any of the optional parameters are not set, they default to the official JSON.org EBNF.
- Booleans
- Case-insensitive (
true,TRUE,True, etc.)
- Case-insensitive (
- Null
- Case-insensitive (
null,NULL)
- Case-insensitive (
Dim decimalSeparator As String = "|"
Dim negativeSign As String = "~"
Dim positiveSign As String = "^"
Dim literal = "123,45"
Dim document As XDocument = JsonTransformer.Parse(literal, decimalSeparator, negativeSign, positiveSign)
Debug.WriteLine(document.ToString())Dim source As String =
"{
""glossary"": {
""title"": ""example glossary"",
""GlossDiv"": {
""title"": ""S"",
""GlossList"": {
""GlossEntry"": {
""ID"": ""SGML"",
""SortAs"": ""SGML"",
""GlossTerm"": ""Standard Generalized Markup Language"",
""Acronym"": ""SGML"",
""Abbrev"": ""ISO 8879:1986"",
""GlossDef"": {
""para"": ""A meta-markup language, used to create markup languages such as DocBook."",
""GlossSeeAlso"": [""GML"", ""XML""]
},
""GlossSee"": ""markup""
}
}
}
}
}"
Dim results As XDocument = Json.JsonTransformer.Parse(source)
Debug.WriteLine(results.ToString())Live Demo: https://dotnetfiddle.net/9E9vDo
This project is free and open source.
Show your support! Your (non-tax deductible) donation of Monero cryptocurrency is a sign of solidarity among web developers.
Being self-taught, I have come a long way over the years. I certainly do not intend on making a living from this free feature, but my hope is to earn a few dollars to validate all of my hard work.
Monero Address: 447SPi8XcexZnF7kYGDboKB6mghWQzRfyScCgDP2r4f2JJTfLGeVcFpKEBT9jazYuW2YG4qn51oLwXpQJ3oEXkeXUsd6TCF
