Skip to content

Commit 923f8f5

Browse files
committed
First plugin: Json.NET
1 parent c3dd084 commit 923f8f5

7 files changed

Lines changed: 445 additions & 1 deletion

File tree

Npgsql.sln

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
33
# Visual Studio 15
4-
VisualStudioVersion = 15.0.26228.4
4+
VisualStudioVersion = 15.0.26621.2
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{4A5A60DD-41B6-40BF-B677-227A921ECCC8}"
77
ProjectSection(SolutionItems) = preProject
@@ -23,6 +23,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Npgsql.Benchmarks", "test\N
2323
EndProject
2424
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSIX", "src\VSIX\VSIX.csproj", "{ECFD8615-DEAD-4498-B262-85A4D0230229}"
2525
EndProject
26+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Npgsql.Json.NET", "src\Npgsql.Json.NET\Npgsql.Json.NET.csproj", "{9CBE603F-6746-411D-A5FD-CB2C948CD7D0}"
27+
EndProject
2628
Global
2729
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2830
Debug|Any CPU = Debug|Any CPU
@@ -71,6 +73,14 @@ Global
7173
{ECFD8615-DEAD-4498-B262-85A4D0230229}.Release|Any CPU.Build.0 = Release|Any CPU
7274
{ECFD8615-DEAD-4498-B262-85A4D0230229}.Release|x86.ActiveCfg = Release|Any CPU
7375
{ECFD8615-DEAD-4498-B262-85A4D0230229}.Release|x86.Build.0 = Release|Any CPU
76+
{9CBE603F-6746-411D-A5FD-CB2C948CD7D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
77+
{9CBE603F-6746-411D-A5FD-CB2C948CD7D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
78+
{9CBE603F-6746-411D-A5FD-CB2C948CD7D0}.Debug|x86.ActiveCfg = Debug|Any CPU
79+
{9CBE603F-6746-411D-A5FD-CB2C948CD7D0}.Debug|x86.Build.0 = Debug|Any CPU
80+
{9CBE603F-6746-411D-A5FD-CB2C948CD7D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
81+
{9CBE603F-6746-411D-A5FD-CB2C948CD7D0}.Release|Any CPU.Build.0 = Release|Any CPU
82+
{9CBE603F-6746-411D-A5FD-CB2C948CD7D0}.Release|x86.ActiveCfg = Release|Any CPU
83+
{9CBE603F-6746-411D-A5FD-CB2C948CD7D0}.Release|x86.Build.0 = Release|Any CPU
7484
EndGlobalSection
7585
GlobalSection(SolutionProperties) = preSolution
7686
HideSolutionNode = FALSE
@@ -81,6 +91,10 @@ Global
8191
{3E9D78D3-C5D4-40E3-9FDD-AC91E19618AB} = {8537E50E-CF7F-49CB-B4EF-3E2A1B11F050}
8292
{8B4AE9B6-CDAC-44DD-A5CD-28A470D363B8} = {ED612DB1-AB32-4603-95E7-891BACA71C39}
8393
{ECFD8615-DEAD-4498-B262-85A4D0230229} = {8537E50E-CF7F-49CB-B4EF-3E2A1B11F050}
94+
{9CBE603F-6746-411D-A5FD-CB2C948CD7D0} = {8537E50E-CF7F-49CB-B4EF-3E2A1B11F050}
95+
EndGlobalSection
96+
GlobalSection(ExtensibilityGlobals) = postSolution
97+
SolutionGuid = {C90AEECD-DB4C-4BE6-B506-16A449852FB8}
8498
EndGlobalSection
8599
GlobalSection(MonoDevelopProperties) = preSolution
86100
StartupItem = Npgsql.csproj

src/Npgsql.Json.NET/JsonHandler.cs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#region License
2+
// The PostgreSQL License
3+
//
4+
// Copyright (C) 2017 The Npgsql Development Team
5+
//
6+
// Permission to use, copy, modify, and distribute this software and its
7+
// documentation for any purpose, without fee, and without a written
8+
// agreement is hereby granted, provided that the above copyright notice
9+
// and this paragraph and the following two paragraphs appear in all copies.
10+
//
11+
// IN NO EVENT SHALL THE NPGSQL DEVELOPMENT TEAM BE LIABLE TO ANY PARTY
12+
// FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
13+
// INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
14+
// DOCUMENTATION, EVEN IF THE NPGSQL DEVELOPMENT TEAM HAS BEEN ADVISED OF
15+
// THE POSSIBILITY OF SUCH DAMAGE.
16+
//
17+
// THE NPGSQL DEVELOPMENT TEAM SPECIFICALLY DISCLAIMS ANY WARRANTIES,
18+
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
19+
// AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
20+
// ON AN "AS IS" BASIS, AND THE NPGSQL DEVELOPMENT TEAM HAS NO OBLIGATIONS
21+
// TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
22+
#endregion
23+
24+
using System;
25+
using System.Collections.Generic;
26+
using System.Text;
27+
using System.Threading;
28+
using System.Threading.Tasks;
29+
using Newtonsoft.Json;
30+
using Newtonsoft.Json.Linq;
31+
using Npgsql.BackendMessages;
32+
using Npgsql.PostgresTypes;
33+
using Npgsql.TypeHandling;
34+
using Npgsql.TypeMapping;
35+
36+
namespace Npgsql.Json.NET
37+
{
38+
class JsonHandlerFactory : NpgsqlTypeHandlerFactory
39+
{
40+
protected override NpgsqlTypeHandler Create(NpgsqlConnection conn)
41+
=> new JsonHandler(conn);
42+
}
43+
44+
class JsonHandler : Npgsql.TypeHandlers.TextHandler
45+
{
46+
public JsonHandler(NpgsqlConnection connection)
47+
: base(connection) {}
48+
49+
protected override async ValueTask<T> Read<T>(NpgsqlReadBuffer buf, int len, bool async, FieldDescription fieldDescription = null)
50+
{
51+
var s = await base.Read<string>(buf, len, async, fieldDescription);
52+
if (typeof(T) == typeof(string))
53+
return (T)(object)s;
54+
try
55+
{
56+
return JsonConvert.DeserializeObject<T>(s);
57+
}
58+
catch (Exception e)
59+
{
60+
throw new NpgsqlSafeReadException(e);
61+
}
62+
}
63+
64+
protected override int ValidateAndGetLength(object value, ref NpgsqlLengthCache lengthCache, NpgsqlParameter parameter = null)
65+
{
66+
var s = value as string;
67+
if (s == null)
68+
{
69+
s = JsonConvert.SerializeObject(value);
70+
if (parameter != null)
71+
parameter.ConvertedValue = s;
72+
}
73+
return base.ValidateAndGetLength(s, ref lengthCache, parameter);
74+
}
75+
76+
protected override Task Write(object value, NpgsqlWriteBuffer buf, NpgsqlLengthCache lengthCache, NpgsqlParameter parameter, bool async)
77+
{
78+
if (parameter?.ConvertedValue != null)
79+
value = parameter.ConvertedValue;
80+
var s = value as string ?? JsonConvert.SerializeObject(value);
81+
return base.Write(s, buf, lengthCache, parameter, async);
82+
}
83+
}
84+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#region License
2+
// The PostgreSQL License
3+
//
4+
// Copyright (C) 2017 The Npgsql Development Team
5+
//
6+
// Permission to use, copy, modify, and distribute this software and its
7+
// documentation for any purpose, without fee, and without a written
8+
// agreement is hereby granted, provided that the above copyright notice
9+
// and this paragraph and the following two paragraphs appear in all copies.
10+
//
11+
// IN NO EVENT SHALL THE NPGSQL DEVELOPMENT TEAM BE LIABLE TO ANY PARTY
12+
// FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
13+
// INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
14+
// DOCUMENTATION, EVEN IF THE NPGSQL DEVELOPMENT TEAM HAS BEEN ADVISED OF
15+
// THE POSSIBILITY OF SUCH DAMAGE.
16+
//
17+
// THE NPGSQL DEVELOPMENT TEAM SPECIFICALLY DISCLAIMS ANY WARRANTIES,
18+
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
19+
// AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
20+
// ON AN "AS IS" BASIS, AND THE NPGSQL DEVELOPMENT TEAM HAS NO OBLIGATIONS
21+
// TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
22+
#endregion
23+
24+
using System;
25+
using System.Threading;
26+
using System.Threading.Tasks;
27+
using Newtonsoft.Json;
28+
using Npgsql.BackendMessages;
29+
using Npgsql.TypeHandling;
30+
using Npgsql.TypeMapping;
31+
32+
namespace Npgsql.Json.NET
33+
{
34+
class JsonbHandlerFactory : NpgsqlTypeHandlerFactory
35+
{
36+
protected override NpgsqlTypeHandler Create(NpgsqlConnection conn)
37+
=> new JsonbHandler(conn);
38+
}
39+
40+
class JsonbHandler : Npgsql.TypeHandlers.JsonbHandler
41+
{
42+
public JsonbHandler(NpgsqlConnection connection)
43+
: base(connection) {}
44+
45+
protected override async ValueTask<T> Read<T>(NpgsqlReadBuffer buf, int len, bool async, FieldDescription fieldDescription = null)
46+
{
47+
var s = await base.Read<string>(buf, len, async, fieldDescription);
48+
if (typeof(T) == typeof(string))
49+
return (T)(object)s;
50+
try
51+
{
52+
return JsonConvert.DeserializeObject<T>(s);
53+
}
54+
catch (Exception e)
55+
{
56+
throw new NpgsqlSafeReadException(e);
57+
}
58+
}
59+
60+
protected override int ValidateAndGetLength(object value, ref NpgsqlLengthCache lengthCache, NpgsqlParameter parameter = null)
61+
{
62+
var s = value as string;
63+
if (s == null)
64+
{
65+
s = JsonConvert.SerializeObject(value);
66+
if (parameter != null)
67+
parameter.ConvertedValue = s;
68+
}
69+
return base.ValidateAndGetLength(s, ref lengthCache, parameter);
70+
}
71+
72+
protected override Task Write(object value, NpgsqlWriteBuffer buf, NpgsqlLengthCache lengthCache, NpgsqlParameter parameter, bool async)
73+
{
74+
if (parameter?.ConvertedValue != null)
75+
value = parameter.ConvertedValue;
76+
var s = value as string ?? JsonConvert.SerializeObject(value);
77+
return base.Write(s, buf, lengthCache, parameter, async);
78+
}
79+
}
80+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<VersionPrefix>1.0.0</VersionPrefix>
5+
<Description>Json.NET plugin for Npgsql, allowing transparent serialization/deserialization of JSON objects directly to and from the database.</Description>
6+
<Authors>Shay Rojansky</Authors>
7+
<Copyright>Copyright 2017 © The Npgsql Development Team</Copyright>
8+
<Company>Npgsql</Company>
9+
<PackageTags>npgsql postgresql json postgres ado ado.net database sql</PackageTags>
10+
<TargetFrameworks>net45;netstandard1.3;netstandard2.0</TargetFrameworks>
11+
<AssemblyOriginatorKeyFile>../../Npgsql.snk</AssemblyOriginatorKeyFile>
12+
<SignAssembly>true</SignAssembly>
13+
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
14+
<WarningsAsErrors>true</WarningsAsErrors>
15+
<GenerateDocumentationFile>true</GenerateDocumentationFile>
16+
<PackageProjectUrl>http://www.npgsql.org</PackageProjectUrl>
17+
<PackageIconUrl>http://www.npgsql.org/img/postgresql.gif</PackageIconUrl>
18+
<PackageLicenseUrl>https://raw.githubusercontent.com/npgsql/npgsql/develop/LICENSE.txt</PackageLicenseUrl>
19+
<RepositoryType>git</RepositoryType>
20+
<RepositoryUrl>git://github.com/npgsql/npgsql</RepositoryUrl>
21+
</PropertyGroup>
22+
23+
<ItemGroup>
24+
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
25+
</ItemGroup>
26+
27+
<ItemGroup>
28+
<ProjectReference Include="..\Npgsql\Npgsql.csproj" />
29+
</ItemGroup>
30+
31+
</Project>
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#region License
2+
// The PostgreSQL License
3+
//
4+
// Copyright (C) 2017 The Npgsql Development Team
5+
//
6+
// Permission to use, copy, modify, and distribute this software and its
7+
// documentation for any purpose, without fee, and without a written
8+
// agreement is hereby granted, provided that the above copyright notice
9+
// and this paragraph and the following two paragraphs appear in all copies.
10+
//
11+
// IN NO EVENT SHALL THE NPGSQL DEVELOPMENT TEAM BE LIABLE TO ANY PARTY
12+
// FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
13+
// INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
14+
// DOCUMENTATION, EVEN IF THE NPGSQL DEVELOPMENT TEAM HAS BEEN ADVISED OF
15+
// THE POSSIBILITY OF SUCH DAMAGE.
16+
//
17+
// THE NPGSQL DEVELOPMENT TEAM SPECIFICALLY DISCLAIMS ANY WARRANTIES,
18+
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
19+
// AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
20+
// ON AN "AS IS" BASIS, AND THE NPGSQL DEVELOPMENT TEAM HAS NO OBLIGATIONS
21+
// TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
22+
#endregion
23+
24+
using System;
25+
using Npgsql.TypeMapping;
26+
using NpgsqlTypes;
27+
28+
namespace Npgsql.Json.NET
29+
{
30+
/// <summary>
31+
/// Extension allowing adding the Json.NET plugin to an Npgsql type mapper.
32+
/// </summary>
33+
public static class NpgsqlJsonNetExtensions
34+
{
35+
/// <summary>
36+
/// Sets up JSON.NET mappings for the PostgreSQL json and jsonb types.
37+
/// </summary>
38+
/// <param name="mapper">The type mapper to set up (global or connection-specific)</param>
39+
/// <param name="jsonbClrTypes">A list of CLR types to map to PostgreSQL jsonb (no need to specify NpgsqlDbType.Jsonb)</param>
40+
/// <param name="jsonClrTypes">A list of CLR types to map to PostgreSQL json (no need to specify NpgsqlDbType.Json)</param>
41+
public static INpgsqlTypeMapper UseJsonNet(this INpgsqlTypeMapper mapper, Type[] jsonbClrTypes = null, Type[] jsonClrTypes = null)
42+
{
43+
mapper.AddMapping(new NpgsqlTypeMappingBuilder
44+
{
45+
PgTypeName = "jsonb",
46+
NpgsqlDbType = NpgsqlDbType.Jsonb,
47+
ClrTypes = jsonbClrTypes,
48+
TypeHandlerFactory = new JsonbHandlerFactory()
49+
}.Build());
50+
51+
mapper.AddMapping(new NpgsqlTypeMappingBuilder
52+
{
53+
PgTypeName = "json",
54+
NpgsqlDbType = NpgsqlDbType.Json,
55+
ClrTypes = jsonClrTypes,
56+
TypeHandlerFactory = new JsonHandlerFactory()
57+
}.Build());
58+
59+
return mapper;
60+
}
61+
}
62+
}

0 commit comments

Comments
 (0)