Imports System.Collections
Imports System.Collections.Generic
Imports System.Globalization
Imports System.Reflection
Imports System.ComponentModel.DataAnnotations
Imports Newtonsoft.Json.Linq
Imports Newtonsoft.Json.Converters
Imports Newtonsoft.Json.Serialization
Public Property MyObjects as List(Of Child) = new List(Of Child)()
Private ReadOnly _Parent As Document
Sub New(Parent As Document)
Function GetParent() As Document
Public Class DocumentContractResolver
Inherits DefaultContractResolver
Private ActiveDocuments As ThreadLocal(Of Stack(Of Document)) = New ThreadLocal(Of Stack(Of Document))(Function() New Stack(Of Document))
Protected Overrides Function CreateContract(ByVal objectType As Type) As JsonContract
Dim contract = MyBase.CreateContract(objectType)
Me.CustomizeDocumentContract(contract)
Me.CustomizeMyObjectContract(contract)
Private Sub CustomizeDocumentContract(ByVal contract As JsonContract)
If GetType(Document).IsAssignableFrom(contract.UnderlyingType) Then
contract.OnDeserializingCallbacks.Add(Sub(o, c) ActiveDocuments.Value.Push(CType(o, Document)))
contract.OnDeserializedCallbacks.Add(Sub(o, c) ActiveDocuments.Value.Pop())
Private Sub CustomizeMyObjectContract(ByVal contract As JsonContract)
If (GetType(Child) = contract.UnderlyingType) Then
contract.DefaultCreator = Function() New Child(ActiveDocuments.Value.Peek())
contract.DefaultCreatorNonPublic = false
Dim inputDoc = New Document()
inputDoc.MyObjects.Add(New Child(inputDoc) With { .Foo = "foo", .Bar = "bar" })
Dim contractResolver = New DocumentContractResolver()
Dim settings = New JsonSerializerSettings() With { .ContractResolver = contractResolver }
Dim jsonString = JsonConvert.SerializeObject(inputDoc, Formatting.Indented, settings)
Console.WriteLine(jsonString)
Dim document = JsonConvert.DeserializeObject(Of Document)(jsonString, settings)
Assert.IsTrue(document.MyObjects.All(Function(o) document.Equals(o.GetParent())))
Dim json2 = JsonConvert.SerializeObject(document, Formatting.Indented, settings)
Assert.IsTrue(JToken.DeepEquals(JToken.Parse(jsonString), JToken.Parse(json2)))
Console.WriteLine("Environment version: " & Environment.Version.ToString())
Console.WriteLine("Json.NET version: " & GetType(JsonSerializer).Assembly.FullName)
Console.WriteLine("Unhandled exception: ")
Public Class AssertionFailedException
Public Sub New(message As String)
Public Sub New(message As String, inner As Exception)
MyBase.New(message, inner)
Public Sub IsTrue(value as Boolean, Optional message as String = "failed")
Throw New AssertionFailedException(message)