Framework/Helpers/JsonHelper.ps1

using namespace Newtonsoft.Json
Set-StrictMode -Version Latest
class JsonHelper {
    static [JsonSerializerSettings] $SerializerSettings = $null;

    hidden static [JsonSerializerSettings] GetSerializerSettings() {
        if (-not [JsonHelper]::SerializerSettings) {
            $settings = [JsonSerializerSettings]::new();
            $settings.Converters.Add([Converters.StringEnumConverter]::new());
            $settings.Formatting = [Formatting]::Indented;
            $settings.NullValueHandling = [NullValueHandling]::Ignore;
            $settings.ReferenceLoopHandling = [ReferenceLoopHandling]::Ignore;
            [JsonHelper]::SerializerSettings = $settings;
        }
        return [JsonHelper]::SerializerSettings;
    }

    static [string] ConvertToJson([PSObject] $dataObject) {
        if ($dataObject) {
            if ($dataObject.GetType() -eq [System.Object[]] -and $dataObject.Count -ne 0) {
                $list = New-Object -TypeName "System.Collections.Generic.List[$($dataObject[0].GetType().fullname)]";
                $dataObject | ForEach-Object {
                    if ($_) {
                        $list.Add($_);
                    }
                }
                return [JsonConvert]::SerializeObject($list, [JsonHelper]::GetSerializerSettings());
            }

            return [JsonConvert]::SerializeObject($dataObject, [JsonHelper]::GetSerializerSettings());
        }
        return "";
    }

    static [string] ConvertToJsonCustom([PSObject] $Object, [Int]$Depth, [Int]$Layers) {
        Set-StrictMode -Off
        $res = [JsonHelper]::ConvertToJsonCustomNotStrict($Object, $Depth, $Layers, $false)
        Set-StrictMode -Version Latest
        return $res
    }

    static [string] ConvertToJsonCustom([PSObject] $Object) {
       return [JsonHelper]::ConvertToJsonCustom($Object, 10, 10);
    }

    static [string] ConvertToJsonCustomCompressed([PSObject] $Object) {
        Set-StrictMode -Off
        $res = [JsonHelper]::ConvertToJsonCustomNotStrict($Object, 10, 0, $false)
        Set-StrictMode -Version Latest
        return $res
    }

    static [string] ConvertToPson([PSObject] $Object) {
        Set-StrictMode -Off
        $res = [JsonHelper]::ConvertToPsonNotStrict($Object, 10, 10, $false, $false, (Get-Variable -Name PSVersionTable).Value.PSVersion)
        Set-StrictMode -Version Latest
        return $res
    }

    static [string] ConvertToJsonCustomNotStrict([PSObject] $Object, [Int]$Depth, [Int]$Layers, [bool]$IsWind) {
        $Format = $Null
        $Quote = If ($Depth -le 0) {""}
        Else {""""}
        $Space = If ($Layers -le 0) {""}
        Else {" "}
        If ($null-eq $Object) { return "null"}
        Else {
            $JSON = If ($Object -is "Array") {
                $Format = "[", ",$Space", "]"
                If ($Depth -gt 1) {
                    For ($i = 0; $i -lt $Object.Count; $i++) {
                        [JsonHelper]::ConvertToJsonCustomNotStrict($Object[$i], $Depth - 1, $Layers - 1, $IsWind)
                    }
                }
            }
            ElseIf ($Object -is "Xml") {
                $String = New-Object System.IO.StringWriter
                $Object.Save($String)
                $Xml = "'" + ([String]$String).Replace("`'", "'") + "'"
                If ($Layers -le 0) {
                    ($Xml -Replace "\r\n\s*", "") -Replace "\s+", " "
                }
                ElseIf ($Layers -eq 1) {
                    $Xml
                }
                Else {
                    $Xml.Replace("`r`n", "`r`n ")
                }
                $String.Dispose()
            }
            ElseIf ($Object -is "Enum") {
                "$Quote$($Object.ToString())$Quote"
            }
            ElseIf ($Object -is "DateTime") {
                "$Quote$($Object.ToString("o"))$Quote"
            }
            ElseIf ($Object -is "TimeSpan") {
                "$Quote$($Object.ToString())$Quote"
            }
            ElseIf ($Object -is "String") {
                $Object = ConvertTo-Json $Object -Depth 1
                "$Object"
            }
            ElseIf ($Object -is "Boolean") {
                If ($Object) {"true"}
                Else {"false"}
            }
            ElseIf ($Object -is "Char") {
                "$Quote$Object$Quote"
            }
            ElseIf ($Object -is "guid") {
                "$Quote$Object$Quote"
            }
            ElseIf ($Object -is "ValueType") {
                $Object
            }
            ElseIf ($Object -is [System.Collections.IDictionary]) {
                If ($null -eq $Object.Keys) {
                    return "null"
                }
                $Format = "{", ",$Space", "}"
                If ($Depth -gt 1) {
                    $Object.GetEnumerator() | ForEach-Object {
                        $Quote + $_.Key + $Quote + "$Space`:$Space" + ([JsonHelper]::ConvertToJsonCustomNotStrict($_.Value, $Depth - 1, $Layers - 1, $IsWind))
                    }
                }
            }
            ElseIf ($Object -is 'System.Collections.IList') {
                $Format = "[", ",$Space", "]"
                If ($Depth -gt 1) {
                    $Object | ForEach-Object {
                        [JsonHelper]::ConvertToJsonCustomNotStrict($_, $Depth - 1, $Layers - 1, $IsWind)
                    }
                }
            }
            ElseIf ($Object -is "Object") {
                If ($Object -is "System.Management.Automation.ErrorRecord" -and !$IsWind) {
                    $Depth = 3
                    $Layers = 3
                    $IsWind = $true
                }
                $Format = "{", ",$Space", "}"
                If ($Depth -gt 1) {
                    Get-Member -InputObject $Object -MemberType Properties | ForEach-Object {
                        $Quote + $_.Name + $Quote + "$Space`:$Space" + ([JsonHelper]::ConvertToJsonCustomNotStrict($Object.$($_.Name), $Depth - 1, $Layers - 1, $IsWind))
                    }
                }
            }
            Else {$Object}
            If ($Format) {
                $JSON = $Format[0] + (& {
                        If (($Layers -le 1) -or ($JSON.Count -le 0)) {
                            $JSON -Join $Format[1]
                        }
                        Else {
                            ("`r`n" + ($JSON -Join "$($Format[1])`r`n")).Replace("`r`n", "`r`n ") + "`r`n"
                        }
                    }) + $Format[2]
            }
            return "$JSON"
        }
    }


    # Adapted from https://stackoverflow.com/questions/15139552/save-hash-table-in-powershell-object-notation-pson
    # PSON - PowerShell Object Notation
    static [string] ConvertToPsonNotStrict([PSObject] $Object, [Int]$Depth, [Int]$Layers, [bool]$IsWind, [bool]$Strict, [Version]$Version) {
        $Format = $Null
        $Quote = If ($Depth -le 0) {""}
        Else {""""}
        $Space = If ($Layers -le 0) {""}
        Else {" "}
        If ($null -eq $Object) {
            return "`$Null"
        }
        Else {
            $Type = "[" + $Object.GetType().Name + "]"
            $PSON = If ($Object -is "Array") {
                $Format = "@(", ",$Space", ")"
                If ($Depth -gt 1) {
                    For ($i = 0; $i -lt $Object.Count; $i++) {
                        [JsonHelper]::ConvertToPsonNotStrict($Object[$i], $Depth - 1, $Layers - 1, $IsWind, $Strict, $Version)
                    }
                }
            }
            ElseIf ($Object -is "Xml") {
                $Type = "[Xml]"
                $String = New-Object System.IO.StringWriter
                $Object.Save($String)
                $Xml = "'" + ([String]$String).Replace("`'", "'") + "'"
                If ($Layers -le 0) {
                    ($Xml -Replace "\r\n\s*", "") -Replace "\s+", " "
                }
                ElseIf ($Layers -eq 1) {
                    $Xml
                }
                Else {
                    $Xml.Replace("`r`n", "`r`n ")
                }
                $String.Dispose()
            }
            ElseIf ($Object -is "Enum") {
                "$Quote$($Object.ToString())$Quote"
            }
            ElseIf ($Object -is "DateTime") {
                "$Quote$($Object.ToString('s'))$Quote"
            }
            ElseIf ($Object -is "TimeSpan") {
                "$Quote$($Object.ToString())$Quote"
            }
            ElseIf ($Object -is "String") {
                0..11 | ForEach-Object {
                    $Object = $Object.Replace([String]"```'""`0`a`b`f`n`r`t`v`$"[$_], ('`' + '`''"0abfnrtv$'[$_]))}; "$Quote$Object$Quote"
            }
            ElseIf ($Object -is "Boolean") {
                If ($Object) {"`$True"}
                Else {"`$False"}
            }
            ElseIf ($Object -is "Char") {
                If ($Strict) {[Int]$Object}
                Else {"$Quote$Object$Quote"}
            }
            ElseIf ($Object -is "guid") {
                "$Quote$Object$Quote"
            }
            ElseIf ($Object -is "ValueType") {
                $Object
            }
            ElseIf ($Object -is [System.Collections.IDictionary]) {
                If ($null -eq $Object.Keys) {
                    return "`$Null"
                }
                If ($Type -eq "[OrderedDictionary]") {$Type = "[Ordered]"}
                $Format = "@{", ";$Space", "}"
                If ($Depth -gt 1) {
                    $Object.GetEnumerator() | ForEach-Object {
                        $Quote + $_.Key + $Quote + "$Space=$Space" + ([JsonHelper]::ConvertToPsonNotStrict($_.Value, $Depth - 1, $Layers - 1, $IsWind, $Strict, $Version))
                    }
                }
            }
            ElseIf ($Object -is 'System.Collections.IList') {
                $Format = "@(", ",$Space", ")"
                If ($Depth -gt 1) {
                    $Object | ForEach-Object {
                        [JsonHelper]::ConvertToPsonNotStrict($_, $Depth - 1, $Layers - 1, $IsWind, $Strict, $Version)
                    }
                }
            }
            ElseIf ($Object -is "Object") {
                If ($Object -is "System.Management.Automation.ErrorRecord" -and !$IsWind) {
                    $Depth = 3
                    $Layers = 3
                    $IsWind = $true
                }
                If ($Version -le [Version]"2.0") {$Type = "New-Object PSObject -Property "}
                $Format = "@{", ";$Space", "}"
                If ($Depth -gt 1) {
                    Get-Member -InputObject $Object -MemberType Properties | ForEach-Object {
                        $Quote + $_.Name + $Quote + "$Space=$Space" + ([JsonHelper]::ConvertToPsonNotStrict($Object.$($_.Name), $Depth - 1, $Layers - 1, $IsWind, $Strict, $Version))
                    }
                }
            }
            Else {$Object}
            If ($Format) {
                $PSON = $Format[0] + (& {
                        If (($Layers -le 1) -or ($PSON.Count -le 0)) {
                            $PSON -Join $Format[1]
                        }
                        Else {
                            ("`r`n" + ($PSON -Join "$($Format[1])`r`n")).Replace("`r`n", "`r`n ") + "`r`n"
                        }
                    }) + $Format[2]
            }
            If ($Strict) {
                return "$Type$PSON"
            }
            Else {
                return "$PSON"
            }
        }
    }

}
# SIG # Begin signature block
# MIInoQYJKoZIhvcNAQcCoIInkjCCJ44CAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDXi3Z8gVnTZE9V
# Y5pGA8ByY3U2ZCaOEzX1Q/TOwvbwgKCCDYEwggX/MIID56ADAgECAhMzAAACUosz
# qviV8znbAAAAAAJSMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
# bmcgUENBIDIwMTEwHhcNMjEwOTAyMTgzMjU5WhcNMjIwOTAxMTgzMjU5WjB0MQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
# AQDQ5M+Ps/X7BNuv5B/0I6uoDwj0NJOo1KrVQqO7ggRXccklyTrWL4xMShjIou2I
# sbYnF67wXzVAq5Om4oe+LfzSDOzjcb6ms00gBo0OQaqwQ1BijyJ7NvDf80I1fW9O
# L76Kt0Wpc2zrGhzcHdb7upPrvxvSNNUvxK3sgw7YTt31410vpEp8yfBEl/hd8ZzA
# v47DCgJ5j1zm295s1RVZHNp6MoiQFVOECm4AwK2l28i+YER1JO4IplTH44uvzX9o
# RnJHaMvWzZEpozPy4jNO2DDqbcNs4zh7AWMhE1PWFVA+CHI/En5nASvCvLmuR/t8
# q4bc8XR8QIZJQSp+2U6m2ldNAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUNZJaEUGL2Guwt7ZOAu4efEYXedEw
# UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1
# ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDY3NTk3MB8GA1UdIwQYMBaAFEhu
# ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu
# bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w
# Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3
# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx
# MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAFkk3
# uSxkTEBh1NtAl7BivIEsAWdgX1qZ+EdZMYbQKasY6IhSLXRMxF1B3OKdR9K/kccp
# kvNcGl8D7YyYS4mhCUMBR+VLrg3f8PUj38A9V5aiY2/Jok7WZFOAmjPRNNGnyeg7
# l0lTiThFqE+2aOs6+heegqAdelGgNJKRHLWRuhGKuLIw5lkgx9Ky+QvZrn/Ddi8u
# TIgWKp+MGG8xY6PBvvjgt9jQShlnPrZ3UY8Bvwy6rynhXBaV0V0TTL0gEx7eh/K1
# o8Miaru6s/7FyqOLeUS4vTHh9TgBL5DtxCYurXbSBVtL1Fj44+Od/6cmC9mmvrti
# yG709Y3Rd3YdJj2f3GJq7Y7KdWq0QYhatKhBeg4fxjhg0yut2g6aM1mxjNPrE48z
# 6HWCNGu9gMK5ZudldRw4a45Z06Aoktof0CqOyTErvq0YjoE4Xpa0+87T/PVUXNqf
# 7Y+qSU7+9LtLQuMYR4w3cSPjuNusvLf9gBnch5RqM7kaDtYWDgLyB42EfsxeMqwK
# WwA+TVi0HrWRqfSx2olbE56hJcEkMjOSKz3sRuupFCX3UroyYf52L+2iVTrda8XW
# esPG62Mnn3T8AuLfzeJFuAbfOSERx7IFZO92UPoXE1uEjL5skl1yTZB3MubgOA4F
# 8KoRNhviFAEST+nG8c8uIsbZeb08SeYQMqjVEmkwggd6MIIFYqADAgECAgphDpDS
# AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK
# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0
# IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0
# ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDlaFw0yNjA3MDgyMTA5MDla
# MH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS
# ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMT
# H01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEwggIiMA0GCSqGSIb3DQEB
# AQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS68rZYIZ9CGypr6VpQqrgG
# OBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15ZId+lGAkbK+eSZzpaF7S
# 35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+erCFDPs0S3XdjELgN1q2jz
# y23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVceaVJKecNvqATd76UPe/7
# 4ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGMXeiJT4Qa8qEvWeSQOy2u
# M1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/U7qcD60ZI4TL9LoDho33
# X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwjp6lm7GEfauEoSZ1fiOIl
# XdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwCgl/bwBWzvRvUVUvnOaEP
# 6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1JMKerjt/sW5+v/N2wZuLB
# l4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3coKPHtbcMojyyPQDdPweGF
# RInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfenk70lrC8RqBsmNLg1oiM
# CwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFEhuZOVQ
# BdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1Ud
# DwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFHItOgIxkEO5FAVO
# 4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwubWljcm9zb2Z0
# LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
# Mi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAChkJodHRwOi8vd3d3Lm1p
# Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
# Mi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4DMIGDMD8GCCsGAQUFBwIB
# FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2RvY3MvcHJpbWFyeWNw
# cy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AcABvAGwAaQBjAHkA
# XwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAGfyhqWY
# 4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjDctFtg/6+P+gKyju/R6mj
# 82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw/WvjPgcuKZvmPRul1LUd
# d5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkFDJvtaPpoLpWgKj8qa1hJ
# Yx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3zDq+ZKJeYTQ49C/IIidYf
# wzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEnGn+x9Cf43iw6IGmYslmJ
# aG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1Fp3blQCplo8NdUmKGwx1j
# NpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0QaxdR8UvmFhtfDcxhsEvt9B
# xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96
# eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7
# r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I
# RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIZdjCCGXICAQEwgZUwfjELMAkG
# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx
# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z
# b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAlKLM6r4lfM52wAAAAACUjAN
# BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor
# BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgxnCG2mxi
# G4NJZUALqcoU1G7BuQdIsQ1M4n3XtMDBAA4wQgYKKwYBBAGCNwIBDDE0MDKgFIAS
# AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN
# BgkqhkiG9w0BAQEFAASCAQBOeeaBBj2rtMye56VF3d7Ta1z9JMffG4zU5uw/5md9
# fZzn8JS8P6v0Bwpb9SjxfoyA9L+dNJxlLt7lPSH2kKHcRYCaqf016yXs8yXyJs6c
# 5O/Ix6QmCcmzHc58/zJYkB3ehR+8OQgoLTx6D/IftYEsN1yipQMhVdTA7ow5ecIm
# nKqBQlfmUfrogksBwJiv0iCa0KRVDJXf1Y7+YnZLhfjFCLXy6Z62QxZ8oF3TjyyZ
# rYX1HS0TlBDvB+a1jpBjRq0f2TTLZdwUJRYE9q6rpPATaCQsGwZgMiAvOvZFH6IM
# Wj/dN5ByK93CboqhH9b7pR3hpDiYKQc/935dSZPiUlaMoYIXADCCFvwGCisGAQQB
# gjcDAwExghbsMIIW6AYJKoZIhvcNAQcCoIIW2TCCFtUCAQMxDzANBglghkgBZQME
# AgEFADCCAVEGCyqGSIb3DQEJEAEEoIIBQASCATwwggE4AgEBBgorBgEEAYRZCgMB
# MDEwDQYJYIZIAWUDBAIBBQAEIATj96pqXvtGPQThC8wPFxGn5QZtp+xJ88wtzqfM
# fn9hAgZiFl+zlxEYEzIwMjIwMzE1MDgzNTE0LjY4NFowBIACAfSggdCkgc0wgcox
# CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt
# b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJTAjBgNVBAsTHE1p
# Y3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlvbnMxJjAkBgNVBAsTHVRoYWxlcyBUU1Mg
# RVNOOjQ5QkMtRTM3QS0yMzNDMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFt
# cCBTZXJ2aWNloIIRVzCCBwwwggT0oAMCAQICEzMAAAGXA89ZnGuJeD8AAQAAAZcw
# DQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0
# b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3Jh
# dGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwHhcN
# MjExMjAyMTkwNTE0WhcNMjMwMjI4MTkwNTE0WjCByjELMAkGA1UEBhMCVVMxEzAR
# BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p
# Y3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2Eg
# T3BlcmF0aW9uczEmMCQGA1UECxMdVGhhbGVzIFRTUyBFU046NDlCQy1FMzdBLTIz
# M0MxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggIiMA0G
# CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDtAErqSkFN8/Ce/csrHVWcv1iSjNTA
# rPKEMqKPUTpYJX8TBZl88LNrpw4bEpPimO+Etcli5RBoZEieo+SzYUnb0+nKEWaE
# Ygubgp+HTFZiD85Lld7mk2Xg91KMDE2yMeOIH2DHpTsn5p0Lf0CDlfPE5HOwpP5/
# vsUxNeDWMW6zsSuKU69aL7Ocyk36VMyCKjHNML67VmZMJBO7bX1vYVShOvQqZUkx
# CpCR3szmxHT09s6nhwLeNCz7nMnU7PEiNGVxSYu+V0ETppFpK7THcGYAMa3SYZjQ
# xGyDOc7J20kEud6tz5ArSRzG47qscDfPYqv1+akex81w395E+1kc4uukfn0CeKtA
# Dum7PqRrbRMD7wyFnX2FvyaytGj0uaKuMXFJsZ+wfdk0RsuPeWHtVz4MRCEwfYr1
# c+JTkmS3n/pvHr/b853do28LoPHezk3dSxbniQojW3BTYJLmrUei/n4BHK5mTT8N
# uxG6zoP3t8HVmhCW//i2sFwxVHPsyQ6sdrxs/hapsPR5sti2ITG/Hge4SeH7Sne9
# 42OHeA/T7sOSJXAhhx9VyUiEUUax+dKIV7Gu67rjq5SVr5VNS4bduOpLsWEjeGHp
# Mei//3xd8dxZ42G/EDkr5+L7UFxIuBAq+r8diP/D8yR/du7vc4RGKw1ppxpo4JH9
# MnYfd+zUDuUgcQIDAQABo4IBNjCCATIwHQYDVR0OBBYEFG3PAc8o6zBullUL0bG+
# 3X69FQBgMB8GA1UdIwQYMBaAFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMF8GA1UdHwRY
# MFYwVKBSoFCGTmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01p
# Y3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNybDBsBggrBgEF
# BQcBAQRgMF4wXAYIKwYBBQUHMAKGUGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9w
# a2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAo
# MSkuY3J0MAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwgwDQYJKoZI
# hvcNAQELBQADggIBAARI2GHSJO0zHnshct+Hgu4dsPU0b0yUsDXBhAdAGdH1T+uD
# eq3c3Hp7v5C4QowSEqp0t/eDlFHhH+hkvm8QlVZR8hIf+hJZ3OqtKGpyZPg7HNzY
# IGzRS2fKilUObhbYK6ajeq7KRg+kGgZ16Ku8N13XncDCwmQgyCb/yzEkpsgF5Pza
# 2etSeA2Y2jy7uXW4TSGwwCrVuK9Drd9Aiev5Wpgm9hPRb/Q9bukDeqHihw2OJfpn
# x32SPHwvu4E8j8ezGJ8KP/yYVG+lUFg7Ko/tjl2LlkCeNMNIcxk1QU8e36eEVdRw
# eNc9FEcIyqomDgPrdfpvRXRHztD3eKnAYhcEzM4xA0i0k5F6Qe0eUuLduDouemOz
# RoKjn9GUcKM2RIOD7FXuph5rfsv84pM2OqYfek0BrcG8/+sNCIYRi+ABtUcQhDPt
# YxZJixZ5Q8VkjfqYKOBRjpXnfwKRC0PAzwEOIBzL6q47x6nKSI/QffbKrAOHznYF
# 5abV60X4+TD+3xc7dD52IW7saCKqN16aPhV+lGyba1M30ecB7CutvRfBjxATa2nS
# FF03ZvRSJLEyYHiE3IopdVoMs4UJ2Iuex+kPSuM4fyNsQJk5tpZYuf14S8Ov5A1A
# +9Livjsv0BrwuvUevjtXAnkTaAISe9jAhEPOkmExGLQqKNg3jfJPpdIZHg32MIIH
# cTCCBVmgAwIBAgITMwAAABXF52ueAptJmQAAAAAAFTANBgkqhkiG9w0BAQsFADCB
# iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1Jl
# ZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMp
# TWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMjEw
# OTMwMTgyMjI1WhcNMzAwOTMwMTgzMjI1WjB8MQswCQYDVQQGEwJVUzETMBEGA1UE
# CBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9z
# b2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQ
# Q0EgMjAxMDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOThpkzntHIh
# C3miy9ckeb0O1YLT/e6cBwfSqWxOdcjKNVf2AX9sSuDivbk+F2Az/1xPx2b3lVNx
# WuJ+Slr+uDZnhUYjDLWNE893MsAQGOhgfWpSg0S3po5GawcU88V29YZQ3MFEyHFc
# UTE3oAo4bo3t1w/YJlN8OWECesSq/XJprx2rrPY2vjUmZNqYO7oaezOtgFt+jBAc
# nVL+tuhiJdxqD89d9P6OU8/W7IVWTe/dvI2k45GPsjksUZzpcGkNyjYtcI4xyDUo
# veO0hyTD4MmPfrVUj9z6BVWYbWg7mka97aSueik3rMvrg0XnRm7KMtXAhjBcTyzi
# YrLNueKNiOSWrAFKu75xqRdbZ2De+JKRHh09/SDPc31BmkZ1zcRfNN0Sidb9pSB9
# fvzZnkXftnIv231fgLrbqn427DZM9ituqBJR6L8FA6PRc6ZNN3SUHDSCD/AQ8rdH
# GO2n6Jl8P0zbr17C89XYcz1DTsEzOUyOArxCaC4Q6oRRRuLRvWoYWmEBc8pnol7X
# KHYC4jMYctenIPDC+hIK12NvDMk2ZItboKaDIV1fMHSRlJTYuVD5C4lh8zYGNRiE
# R9vcG9H9stQcxWv2XFJRXRLbJbqvUAV6bMURHXLvjflSxIUXk8A8FdsaN8cIFRg/
# eKtFtvUeh17aj54WcmnGrnu3tz5q4i6tAgMBAAGjggHdMIIB2TASBgkrBgEEAYI3
# FQEEBQIDAQABMCMGCSsGAQQBgjcVAgQWBBQqp1L+ZMSavoKRPEY1Kc8Q/y8E7jAd
# BgNVHQ4EFgQUn6cVXQBeYl2D9OXSZacbUzUZ6XIwXAYDVR0gBFUwUzBRBgwrBgEE
# AYI3TIN9AQEwQTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29t
# L3BraW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRtMBMGA1UdJQQMMAoGCCsGAQUFBwMI
# MBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMB
# Af8EBTADAQH/MB8GA1UdIwQYMBaAFNX2VsuP6KJcYmjRPZSQW9fOmhjEMFYGA1Ud
# HwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3By
# b2R1Y3RzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNybDBaBggrBgEFBQcBAQRO
# MEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2Vy
# dHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3J0MA0GCSqGSIb3DQEBCwUAA4IC
# AQCdVX38Kq3hLB9nATEkW+Geckv8qW/qXBS2Pk5HZHixBpOXPTEztTnXwnE2P9pk
# bHzQdTltuw8x5MKP+2zRoZQYIu7pZmc6U03dmLq2HnjYNi6cqYJWAAOwBb6J6Gng
# ugnue99qb74py27YP0h1AdkY3m2CDPVtI1TkeFN1JFe53Z/zjj3G82jfZfakVqr3
# lbYoVSfQJL1AoL8ZthISEV09J+BAljis9/kpicO8F7BUhUKz/AyeixmJ5/ALaoHC
# gRlCGVJ1ijbCHcNhcy4sa3tuPywJeBTpkbKpW99Jo3QMvOyRgNI95ko+ZjtPu4b6
# MhrZlvSP9pEB9s7GdP32THJvEKt1MMU0sHrYUP4KWN1APMdUbZ1jdEgssU5HLcEU
# BHG/ZPkkvnNtyo4JvbMBV0lUZNlz138eW0QBjloZkWsNn6Qo3GcZKCS6OEuabvsh
# VGtqRRFHqfG3rsjoiV5PndLQTHa1V1QJsWkBRH58oWFsc/4Ku+xBZj1p/cvBQUl+
# fpO+y/g75LcVv7TOPqUxUYS8vwLBgqJ7Fx0ViY1w/ue10CgaiQuPNtq6TPmb/wrp
# NPgkNWcr4A245oyZ1uEi6vAnQj0llOZ0dFtq0Z4+7X6gMTN9vMvpe784cETRkPHI
# qzqKOghif9lwY1NNje6CbaUFEMFxBmoQtB1VM1izoXBm8qGCAs4wggI3AgEBMIH4
# oYHQpIHNMIHKMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G
# A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUw
# IwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMSYwJAYDVQQLEx1U
# aGFsZXMgVFNTIEVTTjo0OUJDLUUzN0EtMjMzQzElMCMGA1UEAxMcTWljcm9zb2Z0
# IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcGBSsOAwIaAxUAYUDSsI2YSTTNTXYN
# g0YxTcHWY9GggYMwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu
# Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv
# cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDAN
# BgkqhkiG9w0BAQUFAAIFAOXakn0wIhgPMjAyMjAzMTUxMjIwMTNaGA8yMDIyMDMx
# NjEyMjAxM1owdzA9BgorBgEEAYRZCgQBMS8wLTAKAgUA5dqSfQIBADAKAgEAAgIf
# xgIB/zAHAgEAAgIR9jAKAgUA5dvj/QIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgor
# BgEEAYRZCgMCoAowCAIBAAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUA
# A4GBAIGm0/9q/iaAOBhrEmRWL+rLtHB//4bM2Bu7ujcLRDCpo0BtNNubDn7DTuTo
# NLhgPc/e8Q39III9MR0rHG8Y0NFkIz4ojGHHUu8DFfxq2fJUNwM34JbWVfwPPLcZ
# SDVKia2Hip/gDeYDFuwvwQBC4KoCYJBg5bWOboq7vqQlRZy9MYIEDTCCBAkCAQEw
# gZMwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT
# B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UE
# AxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAGXA89ZnGuJeD8A
# AQAAAZcwDQYJYIZIAWUDBAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0B
# CRABBDAvBgkqhkiG9w0BCQQxIgQgf7gkiwgCkVMkR1LaoPJH1/2LNU4WriQfHGa/
# xzAnpiQwgfoGCyqGSIb3DQEJEAIvMYHqMIHnMIHkMIG9BCBbe9obEJV6OP4EDMVJ
# 8zF8dD5vHGSoLDwuQxj9BnimvzCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1w
# IFBDQSAyMDEwAhMzAAABlwPPWZxriXg/AAEAAAGXMCIEIHqR1WMbsgE3KMk79wwA
# AJzTIDDxf4RkTCZ3n/Ri5sQxMA0GCSqGSIb3DQEBCwUABIICAEGG9EWiH1AIUYNj
# Vixt68bm8cvgl3dt9R4jWU8m/6XkhDA7Ac+VqwZG1DoaZl4D9QHKEmhQ9aWmGSwG
# A/KnugZcki+7HlTFLA5zn8up4FDDA4/wjTmle0zt/BmHy3ZRSLdLMOYtSWU3/VGW
# cAEa+G2Ly4dpibvZ3hFeSMVamayKx+m63LMvBNPZpB4Hk+0jyJU9m3gmQ+X6b2/M
# nL9aTAf/zNCG53PY+Yl44iFhXPQT8en6BCn4K7QYMSn1cVWg+MW5Ssz9wkqASObv
# dXKX+/FNMvJTnhE6bQch02WLdP1HJNDSwOtTG6Rz6Y84RRR7YHQehFL0T0FuZ7nx
# bB5GtrB71iB39lNYT9JewkmRI44B/p0Gd2KSqWYItZow8SfUNYZChiIkJPxgBgT6
# cRxs6XAk5svF2pLGrr+di99hMnz3VkySQP1o/Y93Udu7pQpD2w0r+CHqUHRM3Hfn
# tKm5GC70ytm2FUXg8+JyAh712TGnOEkBH48y723hSLcq1evrmywnIDhascWQ1/f9
# 5Mx+ajA2C1ezkwDOCJgAKkW89UT1xpEo8Jc+BThUVjNp1BZPMcGhzfQ4vgGJJYMO
# NQHD5QKiCSOqXs6QHiyOSl0QZQpgpQLnQB6OlqmarjAUn5IfCYT+2jhbX1p/JSkp
# X7+AkJjY6ybvxY2kXC9bGEuZ8QAq
# SIG # End signature block