├── .github ├── dependabot.yml └── workflows │ ├── publish.yml │ └── test.yml ├── .gitignore ├── LICENSE ├── README.md ├── coverage.bat └── src ├── .nuget ├── NuGet.Config └── packages.config ├── NHibernate.Json.AutoLoad.DotSettings ├── NHibernate.Json.Tests ├── Data │ ├── ExampleEntity.cs │ ├── ExampleEntityRepository.cs │ ├── Repository.cs │ └── SessionFactoryProvider.cs ├── JsonColumnPersistanceTests.cs ├── JsonColumnTypeTests.cs ├── JsonCompressorTests.cs ├── JsonConvertorTests.cs └── NHibernate.Json.Tests.csproj ├── NHibernate.Json.sln └── NHibernate.Json ├── Compression ├── DeflateStreamCompressor.cs └── GzipStreamCompressor.cs ├── JsonColumnType.cs ├── JsonCompressor.cs ├── JsonWorker.cs └── NHibernate.Json.csproj /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "nuget" 9 | directory: "/src/" # Location of package manifests 10 | schedule: 11 | interval: "daily" 12 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish to Nuget 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | publish: 10 | name: publish 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | with: 15 | fetch-depth: "0" 16 | - id: tag 17 | uses: Viostream/github-tag-action@v3 18 | env: 19 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 20 | - name: Write out version 21 | run: | 22 | version=${{ steps.tag.outputs.new_tag }} 23 | - name: Build 24 | run: dotnet build -c Release src/NHibernate.Json/NHibernate.Json.csproj 25 | - name: Package 26 | run: | 27 | version=${{ steps.tag.outputs.new_tag }} 28 | dotnet pack -c Release src/NHibernate.Json/NHibernate.Json.csproj -o . -p:PackageVersion=${version#v} 29 | - name: Nuget push 30 | run: dotnet nuget push *.nupkg -s https://api.nuget.org/v3/index.json -k ${{ secrets.NUGET_API_KEY }} --skip-duplicate 31 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | on: ["push", "pull_request"] 2 | 3 | name: Run Tests 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | strategy: 9 | matrix: 10 | dotnet: ['8.0'] 11 | steps: 12 | - uses: actions/checkout@v4 13 | - name: Setup dotnet 14 | uses: actions/setup-dotnet@v4 15 | with: 16 | dotnet-version: ${{ matrix.dotnet }} 17 | - id: test 18 | run: | 19 | cd src 20 | dotnet test --collect:"XPlat Code Coverage" -r output 21 | echo "::set-output name=COVERAGE_FILE::$(find output -name '*.xml')" 22 | # @TODO restore when we get tests working in lcov mode 23 | # - name: Publish coverage to Coveralls 24 | # uses: coverallsapp/github-action@master 25 | # with: 26 | # github-token: ${{ secrets.GITHUB_TOKEN }} 27 | # path-to-lcov: src/${{ steps.test.outputs.COVERAGE_FILE }} 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.suo 2 | *.user 3 | _ReSharper.* 4 | bin/ 5 | obj/ 6 | src/packages/ 7 | src/TestResults 8 | 9 | src/.nuget/NuGet.exe 10 | src/NHibernate.Json.Tests/x64/SQLite.Interop.dll 11 | src/NHibernate.Json.Tests/x86/SQLite.Interop.dll 12 | coverage.xml 13 | src/.vs/ 14 | 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Viocorp International Pty Ltd 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nhibernate-json 2 | NHibernate Custom Type mapping to Json 3 | 4 | This package allows you to map a model to a SQL column storing its contents in Json via serialization. It uses Json.Net for serialisation. 5 | 6 | [![Build status](https://ci.appveyor.com/api/projects/status/2nmlybm3y5tfd2yj?svg=true)](https://ci.appveyor.com/api/projects/status/2nmlybm3y5tfd2yj?svg=true) 7 | [![Coverage Status](https://coveralls.io/repos/github/viostream/nhibernate-json/badge.svg?branch=master)](https://coveralls.io/github/viostream/nhibernate-json?branch=master) 8 | [![NuGet Badge](https://buildstats.info/nuget/Nhibernate.Json)](https://www.nuget.org/packages/Nhibernate.Json/) 9 | 10 | ## Usage 11 | 12 | Using [FluentNHibernate](https://github.com/nhibernate/fluent-nhibernate): Simply add a CustomType to your existing map class 13 | 14 | ```c# 15 | public class ExampleEntityMap : ClassMap 16 | { 17 | public ExampleEntityMap() 18 | { 19 | Table("ExampleEntities"); 20 | Id(x => x.Id).GeneratedBy.Assigned(); 21 | Map(x => x.Title); 22 | Map(x => x.Json).CustomType>().Nullable(); 23 | } 24 | } 25 | ``` 26 | 27 | ## Serialisation Settings 28 | The package uses an internal worker class that has a few pre-set serialisation settings. All of these can be overridden with the standard Json.Net serialisation settings. 29 | 30 | ```c# 31 | JsonWorker.Configure(x => x.TypeNameHandling = TypeNameHandling.None); 32 | ``` 33 | 34 | ## Compression 35 | 36 | As an extra, there is a configurable threshold character length that when your serialised model exceeds, it will become compressed. This increases performance and efficiency by reducing SQL storage space and network traffic. 37 | 38 | You can configure this threshold via the following property: 39 | 40 | ```c# 41 | JsonCompressor.CompressionThreshold = 2000; 42 | ``` 43 | -------------------------------------------------------------------------------- /coverage.bat: -------------------------------------------------------------------------------- 1 | src\packages\OpenCover.4.6.519\tools\OpenCover.Console.exe -output:".\coverage.xml" -target:"src\packages\xunit.runner.console.2.1.0\tools\xunit.console.exe" -targetargs:"NHibernate.Json.Tests.dll" -filter:"+[NHibernate.*]* -[*.Tests]*" -targetdir:src\NHibernate.Json.Tests\bin -register:user 2 | 3 | src\packages\coveralls.net.0.7.0\tools\csmacnz.Coveralls.exe --opencover -i .\coverage.xml 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/.nuget/NuGet.Config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/.nuget/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/NHibernate.Json.AutoLoad.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | ReturnDefaultValue 3 | True 4 | True 5 | True 6 | True 7 | True 8 | True 9 | True 10 | True 11 | True 12 | True 13 | True 14 | True 15 | HINT 16 | <?xml version="1.0" encoding="utf-16"?><Profile name="Viostream default"><CSArrangeThisQualifier>True</CSArrangeThisQualifier><RemoveCodeRedundancies>True</RemoveCodeRedundancies><CSUseAutoProperty>True</CSUseAutoProperty><CSUseVar><BehavourStyle>CAN_CHANGE_TO_IMPLICIT</BehavourStyle><LocalVariableStyle>ALWAYS_IMPLICIT</LocalVariableStyle><ForeachVariableStyle>ALWAYS_IMPLICIT</ForeachVariableStyle></CSUseVar><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSharpFormatDocComments>True</CSharpFormatDocComments><CSReorderTypeMembers>True</CSReorderTypeMembers><XMLReformatCode>True</XMLReformatCode><CSMakeFieldReadonly>True</CSMakeFieldReadonly></Profile> 17 | Viostream default 18 | True 19 | 20 | 21 | True 22 | True 23 | True 24 | NEXT_LINE_SHIFTED_2 25 | 1 26 | TOGETHER_SAME_LINE 27 | False 28 | False 29 | NEXT_LINE_SHIFTED_2 30 | 1 31 | 1 32 | NEVER 33 | 34 | 35 | False 36 | NEVER 37 | False 38 | 39 | 40 | False 41 | 200 42 | 43 | True 44 | OUTLINE 45 | True 46 | True 47 | TEMP_FOLDER 48 | True 49 | True 50 | True 51 | True 52 | True 53 | True 54 | True 55 | True 56 | True 57 | xunit 58 | xunit-assert 59 | xUnit.net Assert.NotSame 60 | True 61 | completeSmart() 62 | 1 63 | True 64 | completeSmart() 65 | 0 66 | True 67 | True 68 | 2.0 69 | InCSharpStatement 70 | ans 71 | True 72 | Xunit.Assert.NotSame($expected$, $actual$);$END$ 73 | True 74 | True 75 | xunit 76 | Create theory method 77 | True 78 | completeSmart() 79 | 1 80 | True 81 | 2 82 | True 83 | 0 84 | True 85 | True 86 | 2.0 87 | InCSharpTypeMember 88 | theory 89 | True 90 | [Xunit.Extensions.TheoryDataAttribute] 91 | [$DataAttribute$] 92 | public void $TheoryMethodName$($parameters$) 93 | { 94 | $END$ 95 | } 96 | True 97 | True 98 | xunit 99 | xunit-assert 100 | xUnit.net Assert.Throws 101 | True 102 | suggestVariableName() 103 | 1 104 | True 105 | completeSmart() 106 | 0 107 | True 108 | True 109 | 3.0 110 | InCSharpStatement 111 | athr 112 | True 113 | var $exception$ = Xunit.Assert.Throws<$TException$>(() => { $END$ }); 114 | True 115 | True 116 | xunit 117 | xunit-assert 118 | xUnit.net Assert.False 119 | True 120 | completeSmart() 121 | 0 122 | True 123 | 1 124 | True 125 | True 126 | 2.0 127 | InCSharpStatement 128 | af 129 | True 130 | Xunit.Assert.False($condition$, $why$);$END$ 131 | True 132 | True 133 | xunit 134 | xunit-assert 135 | xUnit.net Assert.NotEmpty 136 | True 137 | completeSmart() 138 | 0 139 | True 140 | True 141 | 2.0 142 | InCSharpStatement 143 | anm 144 | True 145 | Xunit.Assert.NotEmpty($collection$);$END$ 146 | True 147 | True 148 | xunit 149 | xunit-assert 150 | xUnit.net Assert.Equal 151 | True 152 | completeSmart() 153 | 1 154 | True 155 | completeSmart() 156 | 0 157 | True 158 | True 159 | 2.0 160 | InCSharpStatement 161 | ae 162 | True 163 | Xunit.Assert.Equal($expected$,$actual$);$END$ 164 | True 165 | True 166 | xunit 167 | Create a fact test method 168 | True 169 | 0 170 | True 171 | True 172 | 2.0 173 | InCSharpTypeMember 174 | fact 175 | True 176 | [Xunit.FactAttribute] 177 | public void $FactMethodName$() 178 | { 179 | $END$ 180 | } 181 | True 182 | True 183 | xunit 184 | xunit-assert 185 | xUnit.net Assert.Empty 186 | True 187 | completeSmart() 188 | 0 189 | True 190 | True 191 | 2.0 192 | InCSharpStatement 193 | am 194 | True 195 | Xunit.Assert.Empty($collection$);$END$ 196 | True 197 | True 198 | xunit 199 | xunit-attribute 200 | xUnit.net TheoryAttribute 201 | True 202 | True 203 | 2.0 204 | InCSharpFile 205 | ta 206 | True 207 | [Xunit.Extensions.TheoryAttribute]$END$ 208 | True 209 | True 210 | xunit 211 | xunit-assert 212 | xUnit.net Assert.IsAssignableFrom 213 | True 214 | completeSmart() 215 | 0 216 | True 217 | guessExpectedType() 218 | 1 219 | True 220 | suggestVariableName() 221 | 2 222 | True 223 | True 224 | 2.0 225 | InCSharpStatement 226 | aiaf 227 | True 228 | var $value$ = Xunit.Assert.IsAssignableFrom<$T$>($OBJECT$);$END$ 229 | True 230 | True 231 | xunit 232 | xunit-assert 233 | xUnit.net Assert.Same 234 | True 235 | completeSmart() 236 | 1 237 | True 238 | completeSmart() 239 | 0 240 | True 241 | True 242 | 2.0 243 | InCSharpStatement 244 | as 245 | True 246 | Xunit.Assert.Same($expected$, $actual$);$END$ 247 | True 248 | True 249 | xunit 250 | xunit-attribute 251 | xUnit.net PropertyDataAttribute 252 | True 253 | completeSmart() 254 | 0 255 | True 256 | True 257 | 2.0 258 | InCSharpTypeMember 259 | pda 260 | True 261 | [Xunit.Extensions.PropertyDataAttribute($property$)]$END$ 262 | True 263 | True 264 | xunit 265 | xunit-assert 266 | xUnit.net Assert.DoesNotContain 267 | True 268 | completeSmart() 269 | 1 270 | True 271 | completeSmart() 272 | 0 273 | True 274 | True 275 | 2.0 276 | InCSharpStatement 277 | adnc 278 | True 279 | Xunit.Assert.DoesNotContain($expected$, $collection$);$END$ 280 | True 281 | True 282 | xunit 283 | xunit-assert 284 | xUnit.net Assert.IsNotType 285 | True 286 | completeSmart() 287 | 1 288 | True 289 | completeSmart() 290 | 0 291 | True 292 | True 293 | 2.0 294 | InCSharpStatement 295 | aint 296 | True 297 | Xunit.Assert.IsNotType<$T$>($OBJECT$);$END$ 298 | True 299 | True 300 | xunit 301 | xunit-assert 302 | xUnit.net Assert.True 303 | True 304 | completeSmart() 305 | 0 306 | True 307 | 1 308 | True 309 | True 310 | 2.0 311 | InCSharpStatement 312 | at 313 | True 314 | Xunit.Assert.True($condition$, $why$);$END$ 315 | True 316 | True 317 | xunit 318 | xunit-assert 319 | xUnit.net Assert.IsType 320 | True 321 | completeSmart() 322 | 0 323 | True 324 | guessExpectedType() 325 | 1 326 | True 327 | suggestVariableName() 328 | 2 329 | True 330 | True 331 | 2.0 332 | InCSharpStatement 333 | ait 334 | True 335 | var $value$ = Xunit.Assert.IsType<$T$>($OBJECT$);$END$ 336 | True 337 | True 338 | xunit 339 | xunit-assert 340 | xUnit.net Assert.Contains 341 | True 342 | completeSmart() 343 | 1 344 | True 345 | completeSmart() 346 | 0 347 | True 348 | True 349 | 2.0 350 | InCSharpStatement 351 | ac 352 | True 353 | Xunit.Assert.Contains($expected$, $actual$);$END$ 354 | True 355 | True 356 | xunit 357 | xUnit.net test class 358 | True 359 | 0 360 | True 361 | 1 362 | True 363 | True 364 | 2.0 365 | InCSharpTypeAndNamespace 366 | xtc 367 | True 368 | public class $Classname$ 369 | { 370 | [Xunit.FactAttribute] 371 | public void $Function$() 372 | { 373 | $END$ 374 | } 375 | } 376 | True 377 | True 378 | xunit 379 | xunit-assert 380 | xUnit.net Assert.Null 381 | True 382 | completeSmart() 383 | 0 384 | True 385 | True 386 | 2.0 387 | InCSharpStatement 388 | an 389 | True 390 | Xunit.Assert.Null($Object$);$END$ 391 | True 392 | True 393 | xunit 394 | xunit-assert 395 | xUnit.net Assert.NotInRange 396 | True 397 | completeSmart() 398 | 0 399 | True 400 | completeSmart() 401 | 2 402 | True 403 | completeSmart() 404 | 1 405 | True 406 | True 407 | 2.0 408 | InCSharpStatement 409 | anir 410 | True 411 | Xunit.Assert.NotInRange($actual$, $low$, $high$);$END$ 412 | True 413 | True 414 | xunit 415 | xunit-assert 416 | xUnit.net Assert.DoesNotThrow 417 | True 418 | True 419 | 2.0 420 | InCSharpStatement 421 | adnt 422 | True 423 | Xunit.Assert.DoesNotThrow(() => { $END$ }); 424 | True 425 | True 426 | xunit 427 | xunit-assert 428 | xUnit.net Assert.NotEqual 429 | True 430 | completeSmart() 431 | 1 432 | True 433 | completeSmart() 434 | 0 435 | True 436 | True 437 | 2.0 438 | InCSharpStatement 439 | ane 440 | True 441 | Xunit.Assert.NotEqual($expected$, $actual$);$END$ 442 | True 443 | True 444 | xunit 445 | xunit-assert 446 | xUnit.net Assert.InRange 447 | True 448 | completeSmart() 449 | 0 450 | True 451 | completeSmart() 452 | 2 453 | True 454 | completeSmart() 455 | 1 456 | True 457 | True 458 | 2.0 459 | InCSharpStatement 460 | air 461 | True 462 | Xunit.Assert.InRange($actual$, $low$, $high$);$END$ 463 | True 464 | True 465 | xunit 466 | xunit-assert 467 | xUnit.net Assert.Single 468 | True 469 | completeSmart() 470 | 0 471 | True 472 | suggestVariableName() 473 | 1 474 | True 475 | True 476 | 2.0 477 | InCSharpStatement 478 | a1 479 | True 480 | var $value$ = Xunit.Assert.Single($collection$);$END$ 481 | True 482 | True 483 | xunit 484 | xunit-assert 485 | xUnit.net Assert.PropertyChanged 486 | True 487 | 1 488 | True 489 | completeSmart() 490 | 0 491 | True 492 | True 493 | 2.0 494 | InCSharpStatement 495 | apc 496 | True 497 | Xunit.Assert.PropertyChanged($target$, $property$, () => { $END$ }); 498 | True 499 | True 500 | xunit 501 | xunit-attribute 502 | xUnit.net InlineDataAttribute 503 | True 504 | 0 505 | True 506 | True 507 | 2.0 508 | InCSharpTypeMember 509 | ida 510 | True 511 | [Xunit.Extensions.InlineDataAttribute($data$)]$END$ 512 | True 513 | True 514 | xunit 515 | xunit-attribute 516 | xUnit.net FactAttribute 517 | True 518 | True 519 | 2.0 520 | InCSharpTypeMember 521 | fa 522 | True 523 | [Xunit.FactAttribute] 524 | True 525 | True 526 | xunit 527 | xunit-assert 528 | xUnit.net Assert.NotNull 529 | True 530 | completeSmart() 531 | 0 532 | True 533 | True 534 | 2.0 535 | InCSharpStatement 536 | ann 537 | True 538 | Xunit.Assert.NotNull($Object$);$END$ -------------------------------------------------------------------------------- /src/NHibernate.Json.Tests/Data/ExampleEntity.cs: -------------------------------------------------------------------------------- 1 | namespace NHibernate.Json.Tests.Data 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using FluentNHibernate.Mapping; 6 | 7 | public class ExampleEntity 8 | { 9 | protected ExampleEntity() { } 10 | 11 | public ExampleEntity(int id, string title, ExampleJsonModel json) 12 | { 13 | Id = id; 14 | Title = title; 15 | Json = json; 16 | } 17 | 18 | public virtual int Id { get; set; } 19 | public virtual string Title { get; set; } 20 | public virtual ExampleJsonModel Json { get; set; } 21 | } 22 | 23 | public class ExampleJsonModel 24 | { 25 | public ExampleJsonModel(Guid identifier, List list) 26 | { 27 | Identifier = identifier; 28 | List = list; 29 | } 30 | 31 | public Guid Identifier { get; set; } 32 | public List List { get; set; } 33 | } 34 | 35 | public class ExampleEntityMap : ClassMap 36 | { 37 | public ExampleEntityMap() 38 | { 39 | Table("ExampleEntities"); 40 | Id(x => x.Id).GeneratedBy.Assigned(); 41 | Map(x => x.Title); 42 | Map(x => x.Json).CustomType>().Nullable(); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /src/NHibernate.Json.Tests/Data/ExampleEntityRepository.cs: -------------------------------------------------------------------------------- 1 | namespace NHibernate.Json.Tests.Data 2 | { 3 | public class ExampleEntityRepository : Repository 4 | { 5 | public ExampleEntityRepository(ISession session) 6 | : base(session) {} 7 | } 8 | } -------------------------------------------------------------------------------- /src/NHibernate.Json.Tests/Data/Repository.cs: -------------------------------------------------------------------------------- 1 | namespace NHibernate.Json.Tests.Data 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | public class Repository 7 | { 8 | public Repository(ISession session) 9 | { 10 | Session = session; 11 | } 12 | 13 | public ISession Session { get; private set; } 14 | 15 | public IList FindAll() 16 | { 17 | return Session.CreateCriteria(typeof (T)) 18 | .List(); 19 | } 20 | 21 | public T Save(T entity) 22 | { 23 | Session.Save(entity); 24 | return entity; 25 | } 26 | 27 | public void Flush() 28 | { 29 | Session.Flush(); 30 | } 31 | 32 | public T Find(object id) 33 | { 34 | return Session.Get(id); 35 | } 36 | 37 | #region "Disposing" 38 | 39 | private bool _disposed; 40 | 41 | public void Dispose() 42 | { 43 | Dispose(true); 44 | GC.SuppressFinalize(this); 45 | } 46 | 47 | ~Repository() 48 | { 49 | Dispose(false); 50 | } 51 | 52 | private void Dispose(bool disposing) 53 | { 54 | if (!_disposed) 55 | { 56 | if (disposing) {} 57 | _disposed = true; 58 | } 59 | } 60 | 61 | #endregion 62 | } 63 | } -------------------------------------------------------------------------------- /src/NHibernate.Json.Tests/Data/SessionFactoryProvider.cs: -------------------------------------------------------------------------------- 1 | namespace NHibernate.Json.Tests.Data 2 | { 3 | namespace UnitTests 4 | { 5 | using Cfg; 6 | using FluentNHibernate.Cfg; 7 | using FluentNHibernate.Cfg.Db; 8 | using Tool.hbm2ddl; 9 | 10 | public class SessionFactoryProvider 11 | { 12 | private static SessionFactoryProvider _instance; 13 | private Configuration _configuration; 14 | 15 | private ISessionFactory _sessionFactory; 16 | 17 | private SessionFactoryProvider() {} 18 | 19 | public static SessionFactoryProvider Instance 20 | { 21 | get { return _instance ?? (_instance = new SessionFactoryProvider()); } 22 | } 23 | 24 | public void Initialize() 25 | { 26 | _sessionFactory = CreateSessionFactory(); 27 | } 28 | 29 | private ISessionFactory CreateSessionFactory() 30 | { 31 | return Fluently.Configure() 32 | .Database(SQLiteConfiguration.Standard.InMemory().ShowSql()) 33 | .Mappings(m => m.FluentMappings.AddFromAssemblyOf()) 34 | .ExposeConfiguration(cfg => _configuration = cfg) 35 | .BuildSessionFactory(); 36 | } 37 | 38 | public ISession OpenSession() 39 | { 40 | ISession session = _sessionFactory.OpenSession(); 41 | 42 | var export = new SchemaExport(_configuration); 43 | export.Execute(true, true, false, session.Connection, null); 44 | 45 | return session; 46 | } 47 | 48 | public void Dispose() 49 | { 50 | if (_sessionFactory != null) 51 | _sessionFactory.Dispose(); 52 | 53 | _sessionFactory = null; 54 | _configuration = null; 55 | } 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /src/NHibernate.Json.Tests/JsonColumnPersistanceTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace NHibernate.Json.Tests 8 | { 9 | using Data; 10 | using Data.UnitTests; 11 | using Xunit; 12 | 13 | public class JsonColumnPersistanceTests : IDisposable 14 | { 15 | public JsonColumnPersistanceTests() 16 | { 17 | SessionFactoryProvider.Instance.Initialize(); 18 | } 19 | 20 | [Fact] 21 | public void CanSetupSession() 22 | { 23 | var session = SessionFactoryProvider.Instance.OpenSession(); 24 | 25 | var repo = new ExampleEntityRepository(session); 26 | Assert.NotNull(repo); 27 | } 28 | 29 | [Fact] 30 | public void Persist_NoCompression() 31 | { 32 | var session = SessionFactoryProvider.Instance.OpenSession(); 33 | 34 | var id = 12; 35 | var identifer = Guid.NewGuid(); 36 | var repo = new ExampleEntityRepository(session); 37 | var entity = new ExampleEntity(id, "Something", new ExampleJsonModel(identifer, new List())); 38 | repo.Save(entity); 39 | repo.Flush(); 40 | 41 | var found = repo.FindAll(); 42 | 43 | Assert.Equal(1, found.Count); 44 | 45 | Assert.Equal(id, entity.Id); 46 | Assert.Equal("Something", found.First().Title); 47 | Assert.Equal(identifer, entity.Json.Identifier); 48 | session.Dispose(); 49 | } 50 | 51 | [Fact] 52 | public void Persist_Compression() 53 | { 54 | var session = SessionFactoryProvider.Instance.OpenSession(); 55 | JsonCompressor.CompressionThreshold = 10; 56 | var id = 12; 57 | var identifer = Guid.NewGuid(); 58 | var repo = new ExampleEntityRepository(session); 59 | var entity = new ExampleEntity(id, "Something", new ExampleJsonModel(identifer, new List {"AAAAAA","BBBBBBBB","CCCCCCC", "DDDDDDD"})); 60 | repo.Save(entity); 61 | repo.Flush(); 62 | 63 | var found = repo.FindAll(); 64 | 65 | Assert.Equal(1, found.Count); 66 | 67 | Assert.Equal(id, entity.Id); 68 | Assert.Equal("Something", found.First().Title); 69 | Assert.Equal(identifer, entity.Json.Identifier); 70 | Assert.Equal("AAAAAA", entity.Json.List.First()); 71 | session.Dispose(); 72 | JsonCompressor.CompressionThreshold = 10000; 73 | } 74 | 75 | public void Dispose() 76 | { 77 | SessionFactoryProvider.Instance.Dispose(); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/NHibernate.Json.Tests/JsonColumnTypeTests.cs: -------------------------------------------------------------------------------- 1 | namespace NHibernate.Json.Tests 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using Data; 6 | using Xunit; 7 | 8 | public class JsonColumnTypeTests 9 | { 10 | 11 | [Fact] 12 | public void DeepCopy_Success() 13 | { 14 | var id = Guid.NewGuid(); 15 | var value = (object)(new ExampleJsonModel(id, new List{"1","2"})); 16 | var type = new JsonColumnType(); 17 | var result = type.DeepCopy(value) as ExampleJsonModel; 18 | 19 | Assert.NotNull(result); 20 | Assert.Equal(id, result.Identifier); 21 | } 22 | 23 | [Fact] 24 | public void DeepCopy_Null() 25 | { 26 | object value = null; 27 | var type = new JsonColumnType(); 28 | 29 | var result = type.DeepCopy(value); 30 | Assert.Null(result); 31 | } 32 | 33 | [Fact] 34 | public void Serialise_Success() 35 | { 36 | var id = new Guid("7D1E8984-15FD-4FCD-85FF-DF248C1E056B"); 37 | var type = new JsonColumnType(); 38 | var value = new ExampleJsonModel(id, new List { "1", "2" }); 39 | var result = type.Serialise(value); 40 | Assert.NotNull(result); 41 | Assert.Equal("{\"identifier\":\"7d1e8984-15fd-4fcd-85ff-df248c1e056b\",\"list\":[\"1\",\"2\"]}", result); 42 | } 43 | 44 | [Fact] 45 | public void Serialise_Null() 46 | { 47 | var type = new JsonColumnType(); 48 | var result = type.Serialise(null); 49 | Assert.NotNull(result); 50 | Assert.Equal("{}", result); 51 | } 52 | 53 | [Fact] 54 | public void Deserialise_Success() 55 | { 56 | var id = new Guid("7D1E8984-15FD-4FCD-85FF-DF248C1E056B"); 57 | var value = "{\"identifier\":\""+id+"\",\"list\":[\"1\",\"2\"]}"; 58 | var type = new JsonColumnType(); 59 | var result = type.Deserialise(value); 60 | Assert.NotNull(result); 61 | Assert.Equal(id, result.Identifier); 62 | } 63 | 64 | [Fact] 65 | public void Deserialise_Null() 66 | { 67 | var type = new JsonColumnType(); 68 | var result = type.Deserialise(null); 69 | Assert.NotNull(result); 70 | } 71 | 72 | [Fact] 73 | public void Deserialise_EmptyString() 74 | { 75 | var type = new JsonColumnType(); 76 | var result = type.Deserialise(""); 77 | Assert.NotNull(result); 78 | } 79 | 80 | [Fact] 81 | public void Equals_Success() 82 | { 83 | var id = Guid.NewGuid(); 84 | var type = new JsonColumnType(); 85 | var result = type.Equals(new ExampleJsonModel(id, new List()), new ExampleJsonModel(id, new List())); 86 | Assert.True(result); 87 | } 88 | 89 | [Fact] 90 | public void Equals_Fail() 91 | { 92 | var id = Guid.NewGuid(); 93 | var type = new JsonColumnType(); 94 | var result = type.Equals(string.Empty, new ExampleJsonModel(id, new List())); 95 | Assert.False(result); 96 | } 97 | } 98 | } -------------------------------------------------------------------------------- /src/NHibernate.Json.Tests/JsonCompressorTests.cs: -------------------------------------------------------------------------------- 1 | namespace NHibernate.Json.Tests 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Reflection; 6 | using Data; 7 | using Xunit; 8 | using Xunit.Sdk; 9 | 10 | public class JsonCompressorTests 11 | { 12 | [Fact] 13 | public void ConfigureThreshold_Success() 14 | { 15 | JsonCompressor.CompressionThreshold = 10000; 16 | 17 | Assert.Equal(10000, JsonCompressor.CompressionThreshold); 18 | } 19 | 20 | [Fact] 21 | public void CompressZlib_Success() 22 | { 23 | var id = new Guid("209EBBA5-F195-495F-BA68-48C32173BEC5"); 24 | var model = new ExampleJsonModel(id, new List { "a", "b" }); 25 | 26 | var serialised = JsonWorker.Serialize(model); 27 | var compressed = JsonCompressor.Compress(serialised, threshold:10); 28 | Assert.DoesNotContain("{\"identifier\":", compressed); 29 | } 30 | 31 | [Fact] 32 | public void CompressZlib_Success_UnderThreshold() 33 | { 34 | var id = new Guid("209EBBA5-F195-495F-BA68-48C32173BEC5"); 35 | var model = new ExampleJsonModel(id, new List { "a", "b" }); 36 | 37 | var serialised = JsonWorker.Serialize(model); 38 | var compressed = JsonCompressor.Compress(serialised); 39 | Assert.Equal("{\"identifier\":\"" + id + "\",\"list\":[\"a\",\"b\"]}", compressed); 40 | } 41 | 42 | [Fact] 43 | public void DecrompressZlib_Success() 44 | { 45 | var id = new Guid("209EBBA5-F195-495F-BA68-48C32173BEC5"); 46 | var model = new ExampleJsonModel(id, new List { "a", "b" }); 47 | 48 | var serialised = JsonWorker.Serialize(model); 49 | var compressed = JsonCompressor.Compress(serialised, threshold:10); 50 | var decompressed = JsonCompressor.Decompress(compressed); 51 | Assert.Equal("{\"identifier\":\"" + id + "\",\"list\":[\"a\",\"b\"]}", decompressed); 52 | } 53 | 54 | [Fact] 55 | public void DecompressZlib_Success_UnderThreshold() 56 | { 57 | var id = new Guid("209EBBA5-F195-495F-BA68-48C32173BEC5"); 58 | var model = new ExampleJsonModel(id, new List { "a", "b" }); 59 | 60 | var serialised = JsonWorker.Serialize(model); 61 | var compressed = JsonCompressor.Compress(serialised); 62 | var decompressed = JsonCompressor.Decompress(compressed); 63 | Assert.Equal("{\"identifier\":\"" + id + "\",\"list\":[\"a\",\"b\"]}", decompressed); 64 | } 65 | 66 | [Fact] 67 | public void CompressGzip_Success() 68 | { 69 | var id = new Guid("209EBBA5-F195-495F-BA68-48C32173BEC5"); 70 | var model = new ExampleJsonModel(id, new List { "a", "b" }); 71 | 72 | var serialised = JsonWorker.Serialize(model); 73 | var compressed = JsonCompressor.Compress(serialised, Compressor.Gzip, 10); 74 | Assert.DoesNotContain("{\"identifier\":", compressed); 75 | } 76 | 77 | [Fact] 78 | public void CompressGzip_Success_UnderThreshold() 79 | { 80 | var id = new Guid("209EBBA5-F195-495F-BA68-48C32173BEC5"); 81 | var model = new ExampleJsonModel(id, new List { "a", "b" }); 82 | 83 | var serialised = JsonWorker.Serialize(model); 84 | var compressed = JsonCompressor.Compress(serialised, Compressor.Gzip); 85 | Assert.Equal("{\"identifier\":\"" + id + "\",\"list\":[\"a\",\"b\"]}", compressed); 86 | } 87 | 88 | [Fact] 89 | public void DecompressGzip_Success() 90 | { 91 | var id = new Guid("209EBBA5-F195-495F-BA68-48C32173BEC5"); 92 | var model = new ExampleJsonModel(id, new List { "a", "b" }); 93 | 94 | var serialised = JsonWorker.Serialize(model); 95 | var compressed = JsonCompressor.Compress(serialised, Compressor.Gzip, 10); 96 | var decompressed = JsonCompressor.Decompress(compressed, Compressor.Gzip); 97 | Assert.Equal("{\"identifier\":\"" + id + "\",\"list\":[\"a\",\"b\"]}", decompressed); 98 | } 99 | 100 | [Fact] 101 | public void DecompressGzip_Success_UnderThreshold() 102 | { 103 | var id = new Guid("209EBBA5-F195-495F-BA68-48C32173BEC5"); 104 | var model = new ExampleJsonModel(id, new List { "a", "b" }); 105 | 106 | var serialised = JsonWorker.Serialize(model); 107 | var compressed = JsonCompressor.Compress(serialised, Compressor.Gzip, 10); 108 | var decompressed = JsonCompressor.Decompress(compressed, Compressor.Gzip); 109 | Assert.Equal("{\"identifier\":\"" + id + "\",\"list\":[\"a\",\"b\"]}", decompressed); 110 | } 111 | } 112 | } -------------------------------------------------------------------------------- /src/NHibernate.Json.Tests/JsonConvertorTests.cs: -------------------------------------------------------------------------------- 1 | namespace NHibernate.Json.Tests 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using Data; 6 | using Newtonsoft.Json; 7 | using Util; 8 | using Xunit; 9 | 10 | public class JsonConvertorTests 11 | { 12 | [Fact] 13 | public void CanConfigureProperty() 14 | { 15 | JsonWorker.Configure(x => x.TypeNameHandling = TypeNameHandling.None); 16 | 17 | Assert.Equal(TypeNameHandling.None, JsonWorker.Settings.TypeNameHandling); 18 | } 19 | 20 | [Fact] 21 | public void Serialise_Success() 22 | { 23 | var id = new Guid("209EBBA5-F195-495F-BA68-48C32173BEC5"); 24 | var model = new ExampleJsonModel(id, new List {"a", "b"}); 25 | 26 | var serialised = JsonWorker.Serialize(model); 27 | 28 | Assert.Equal("{\"identifier\":\"" + id + "\",\"list\":[\"a\",\"b\"]}", serialised); 29 | } 30 | 31 | [Fact] 32 | public void Deserialise_Success() 33 | { 34 | var id = new Guid("209EBBA5-F195-495F-BA68-48C32173BEC5"); 35 | var json = "{\"identifier\":\"" + id + "\",\"list\":[\"a\",\"b\"]}"; 36 | 37 | var model = JsonWorker.Deserialize(json); 38 | 39 | Assert.Equal(id, model.Identifier); 40 | Assert.Equal("a", model.List.First()); 41 | } 42 | 43 | [Fact] 44 | public void PopulateObject_Success() 45 | { 46 | var id = new Guid("209EBBA5-F195-495F-BA68-48C32173BEC5"); 47 | var json = "{\"identifier\":\"" + id + "\",\"list\":[\"a\",\"b\"]}"; 48 | 49 | var model = new ExampleJsonModel(Guid.NewGuid(), new List()); 50 | JsonWorker.PopulateObject(json, model); 51 | 52 | Assert.Equal(id, model.Identifier); 53 | Assert.Equal("a", model.List.First()); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /src/NHibernate.Json.Tests/NHibernate.Json.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | all 16 | runtime; build; native; contentfiles; analyzers; buildtransitive 17 | 18 | 19 | all 20 | runtime; build; native; contentfiles; analyzers; buildtransitive 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/NHibernate.Json.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30523.141 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NHibernate.Json", "NHibernate.Json\NHibernate.Json.csproj", "{F3C17702-8A51-41C3-B3FF-3E3F64A28947}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NHibernate.Json.Tests", "NHibernate.Json.Tests\NHibernate.Json.Tests.csproj", "{19041788-6D93-4758-88B4-98FF5FF768B0}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {F3C17702-8A51-41C3-B3FF-3E3F64A28947}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {F3C17702-8A51-41C3-B3FF-3E3F64A28947}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {F3C17702-8A51-41C3-B3FF-3E3F64A28947}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {F3C17702-8A51-41C3-B3FF-3E3F64A28947}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {19041788-6D93-4758-88B4-98FF5FF768B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {19041788-6D93-4758-88B4-98FF5FF768B0}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {19041788-6D93-4758-88B4-98FF5FF768B0}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {19041788-6D93-4758-88B4-98FF5FF768B0}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {1E209B26-78D5-4421-AB74-D5DF0806DD4D} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /src/NHibernate.Json/Compression/DeflateStreamCompressor.cs: -------------------------------------------------------------------------------- 1 | namespace NHibernate.Json.Compression 2 | { 3 | using System; 4 | using System.IO; 5 | using System.IO.Compression; 6 | using System.Text; 7 | 8 | internal class DeflateStreamCompressor 9 | { 10 | public static string Compress(string value) 11 | { 12 | using (var memoryStream = new MemoryStream()) 13 | { 14 | using (var zipStream = new DeflateStream(memoryStream, CompressionMode.Compress)) 15 | using (var writer = new StreamWriter(zipStream, Encoding.Unicode)) 16 | { 17 | writer.Write(value); 18 | } 19 | 20 | return Convert.ToBase64String(memoryStream.ToArray()); 21 | } 22 | } 23 | 24 | public static string Decompress(byte[] bytes) 25 | { 26 | using (var memoryStream = new MemoryStream(bytes)) 27 | using (var zipStream = new DeflateStream(memoryStream, CompressionMode.Decompress)) 28 | using (var reader = new StreamReader(zipStream, Encoding.Unicode)) 29 | { 30 | return reader.ReadToEnd(); 31 | } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/NHibernate.Json/Compression/GzipStreamCompressor.cs: -------------------------------------------------------------------------------- 1 | namespace NHibernate.Json.Compression 2 | { 3 | using System; 4 | using System.IO; 5 | using System.IO.Compression; 6 | using System.Text; 7 | 8 | internal class GzipStreamCompressor 9 | { 10 | public static string Compress(string value) 11 | { 12 | using (var memoryStream = new MemoryStream()) 13 | { 14 | using (var zipStream = new GZipStream(memoryStream, CompressionMode.Compress)) 15 | using (var writer = new StreamWriter(zipStream, Encoding.Unicode)) 16 | { 17 | writer.Write(value); 18 | } 19 | 20 | return Convert.ToBase64String(memoryStream.ToArray()); 21 | } 22 | } 23 | 24 | public static string Decompress(byte[] bytes) 25 | { 26 | using (var memoryStream = new MemoryStream(bytes)) 27 | using (var zipStream = new GZipStream(memoryStream, CompressionMode.Decompress)) 28 | using (var reader = new StreamReader(zipStream, Encoding.Unicode)) 29 | { 30 | return reader.ReadToEnd(); 31 | } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/NHibernate.Json/JsonColumnType.cs: -------------------------------------------------------------------------------- 1 | namespace NHibernate.Json 2 | { 3 | using System; 4 | using System.Data.Common; 5 | using System.Runtime.Serialization; 6 | using Engine; 7 | using SqlTypes; 8 | using UserTypes; 9 | 10 | public class JsonColumnType : IUserType where T : class 11 | { 12 | public Type ReturnedType => typeof(T); 13 | 14 | public bool IsMutable 15 | { 16 | get { return false; } 17 | } 18 | 19 | public SqlType[] SqlTypes 20 | { 21 | get { return new[] {SqlTypeFactory.GetString(8000)}; } 22 | } 23 | 24 | public object Assemble(object cached, object owner) 25 | { 26 | return cached; 27 | } 28 | 29 | public object DeepCopy(object value) 30 | { 31 | var source = value as T; 32 | if (source == null) 33 | return null; 34 | return Deserialise(Serialise(source)); 35 | } 36 | 37 | public object Disassemble(object value) 38 | { 39 | return value; 40 | } 41 | 42 | public new bool Equals(object x, object y) 43 | { 44 | var left = x as T; 45 | var right = y as T; 46 | 47 | if (left == null && right == null) 48 | return true; 49 | 50 | if (left == null || right == null) 51 | return false; 52 | 53 | return Serialise(left).Equals(Serialise(right)); 54 | } 55 | 56 | public int GetHashCode(object x) 57 | { 58 | return x.GetHashCode(); 59 | } 60 | 61 | public virtual object NullSafeGet(DbDataReader rs, string[] names, ISessionImplementor session, object owner) 62 | { 63 | var returnValue = NHibernateUtil.String.NullSafeGet(rs, names[0], session); 64 | var json = returnValue == null ? "{}" : returnValue.ToString(); 65 | return Deserialise(json); 66 | } 67 | 68 | public virtual void NullSafeSet(DbCommand cmd, object value, int index, ISessionImplementor session) 69 | { 70 | var column = value as T; 71 | if (value == null) 72 | { 73 | NHibernateUtil.String.NullSafeSet(cmd, "{}", index, session); 74 | return; 75 | } 76 | 77 | value = Serialise(column); 78 | NHibernateUtil.String.NullSafeSet(cmd, value, index, session); 79 | } 80 | 81 | public virtual object Replace(object original, object target, object owner) 82 | { 83 | return original; 84 | } 85 | 86 | public T Deserialise(string jsonString) 87 | { 88 | if (string.IsNullOrWhiteSpace(jsonString)) 89 | return CreateObject(typeof(T)); 90 | 91 | var decompressed = JsonCompressor.Decompress(jsonString); 92 | return JsonWorker.Deserialize(decompressed); 93 | } 94 | 95 | public string Serialise(T obj) 96 | { 97 | if (obj == null) 98 | return "{}"; 99 | var serialised = JsonWorker.Serialize(obj); 100 | return JsonCompressor.Compress(serialised); 101 | } 102 | 103 | private static T CreateObject(Type jsonType) 104 | { 105 | object result; 106 | try 107 | { 108 | result = Activator.CreateInstance(jsonType, true); 109 | } 110 | catch (Exception) 111 | { 112 | result = FormatterServices.GetUninitializedObject(jsonType); 113 | } 114 | 115 | return (T) result; 116 | } 117 | } 118 | } -------------------------------------------------------------------------------- /src/NHibernate.Json/JsonCompressor.cs: -------------------------------------------------------------------------------- 1 | namespace NHibernate.Json 2 | { 3 | using System; 4 | using Compression; 5 | 6 | public class JsonCompressor 7 | { 8 | public static int CompressionThreshold = 2000; 9 | 10 | public static string Compress(string value, Compressor compressor = Compressor.Zlib, int threshold = 0) 11 | { 12 | threshold = threshold > 0 ? threshold : CompressionThreshold; 13 | if (!string.IsNullOrEmpty(value) && value.Length < threshold) 14 | return value; 15 | 16 | return compressor == Compressor.Gzip ? GzipStreamCompressor.Compress(value) : DeflateStreamCompressor.Compress(value); 17 | } 18 | 19 | public static string Decompress(string value, Compressor compressor = Compressor.Zlib) 20 | { 21 | if (value == null) 22 | return "{}"; 23 | 24 | if (value.StartsWith("{")) 25 | return value; 26 | 27 | byte[] bytes; 28 | var isZipped = value.StartsWith("H4sI"); 29 | 30 | if (isZipped) 31 | compressor = Compressor.Gzip; 32 | try 33 | { 34 | bytes = Convert.FromBase64String(value); 35 | } 36 | catch (Exception) 37 | { 38 | return value; 39 | } 40 | 41 | return compressor == Compressor.Gzip ? GzipStreamCompressor.Decompress(bytes) : DeflateStreamCompressor.Decompress(bytes); 42 | } 43 | } 44 | 45 | public enum Compressor 46 | { 47 | Gzip, 48 | Zlib 49 | } 50 | } -------------------------------------------------------------------------------- /src/NHibernate.Json/JsonWorker.cs: -------------------------------------------------------------------------------- 1 | namespace NHibernate.Json 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using Newtonsoft.Json; 7 | using Newtonsoft.Json.Converters; 8 | using Newtonsoft.Json.Serialization; 9 | 10 | public class JsonWorker 11 | { 12 | public static readonly JsonSerializerSettings Settings; 13 | 14 | static JsonWorker() 15 | { 16 | Settings = new JsonSerializerSettings 17 | { 18 | ContractResolver = new CamelCasePropertyNamesContractResolver(), 19 | Converters = new List {new StringEnumConverter()}, 20 | ObjectCreationHandling = ObjectCreationHandling.Auto, 21 | ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor, 22 | TypeNameHandling = TypeNameHandling.Auto 23 | }; 24 | } 25 | 26 | public static JsonSerializerSettings Configure(params Action[] actions) 27 | { 28 | actions.ToList().ForEach(x => x(Settings)); 29 | return Settings; 30 | } 31 | 32 | public static string Serialize(object obj) 33 | { 34 | return JsonConvert.SerializeObject(obj, Formatting.None, Settings); 35 | } 36 | 37 | public static T Deserialize(string json) 38 | { 39 | return JsonConvert.DeserializeObject(json, Settings); 40 | } 41 | 42 | public static void PopulateObject(string json, T obj) 43 | { 44 | JsonConvert.PopulateObject(json, obj, Settings); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /src/NHibernate.Json/NHibernate.Json.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | Viostream 6 | https://github.com/Viostream/nhibernate-json 7 | NHibernate Json column is a custom column mapping that allows you to store complex models as Json in a sql column, with optional and configurable text compression. 8 | Copyright ©2020 Viocorp International P/L 9 | MIT 10 | nhibernate;json 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | --------------------------------------------------------------------------------