Skip to content

Commit 3982973

Browse files
author
Jared Bienz
committed
Greatly improved deserialization from Json. No converters needed. Using a contract resolver to handle the way Unity needs objects instantiated.
1 parent 7b2587b commit 3982973

File tree

9 files changed

+313
-2
lines changed

9 files changed

+313
-2
lines changed

SpatialAlignment-Unity/Assembly-CSharp.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,8 +829,11 @@
829829
<Compile Include="Assets\HoloToolkit-Preview\SpectatorView\UnityARKitPlugin\Plugins\iOS\UnityARKit\NativeInterface\UnityARSessionNativeInterface.cs" />
830830
<Compile Include="Assets\SpatialAlignment\Persistence\INativePersistence.cs" />
831831
<Compile Include="Assets\SpatialAlignment\Persistence\ISpatialAlignmentStore.cs" />
832+
<Compile Include="Assets\SpatialAlignment\Persistence\Json\AlignmentStrategyConverter.cs" />
832833
<Compile Include="Assets\SpatialAlignment\Persistence\Json\JsonStore.cs" />
834+
<Compile Include="Assets\SpatialAlignment\Persistence\Json\SpatialContractResolver.cs" />
833835
<Compile Include="Assets\SpatialAlignment\Persistence\Json\SpatialFrameConverter.cs" />
836+
<Compile Include="Assets\SpatialAlignment\Persistence\Json\UnityContractResolver.cs" />
834837
<Compile Include="Assets\SpatialAlignment\Persistence\Json\Vector3Converter.cs" />
835838
<Compile Include="Assets\SpatialAlignment\SpatialAlignmentManager.cs" />
836839
<Compile Include="Assets\SpatialAlignment\SpatialFrame.cs" />
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//
2+
// Copyright (c) Microsoft. All rights reserved.
3+
// Licensed under the MIT license.
4+
//
5+
// MIT License:
6+
// Permission is hereby granted, free of charge, to any person obtaining
7+
// a copy of this software and associated documentation files (the
8+
// "Software"), to deal in the Software without restriction, including
9+
// without limitation the rights to use, copy, modify, merge, publish,
10+
// distribute, sublicense, and/or sell copies of the Software, and to
11+
// permit persons to whom the Software is furnished to do so, subject to
12+
// the following conditions:
13+
//
14+
// The above copyright notice and this permission notice shall be
15+
// included in all copies or substantial portions of the Software.
16+
//
17+
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
18+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20+
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21+
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22+
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23+
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24+
//
25+
26+
using Newtonsoft.Json;
27+
using Newtonsoft.Json.Converters;
28+
using System;
29+
using System.Collections.Generic;
30+
using System.Linq;
31+
using System.Text;
32+
using System.Threading.Tasks;
33+
using UnityEngine;
34+
35+
namespace Microsoft.SpatialAlignment.Persistence.Json
36+
{
37+
public class AlignmentStrategyConverter : CustomCreationConverter<IAlignmentStrategy>
38+
{
39+
public override IAlignmentStrategy Create(Type objectType)
40+
{
41+
throw new NotImplementedException();
42+
}
43+
44+
//public override bool CanConvert(Type objectType)
45+
//{
46+
// return typeof(IAlignmentStrategy).IsAssignableFrom(objectType);
47+
//}
48+
49+
//public override bool CanWrite => false; // Only use for read operations, not write operations.
50+
51+
//public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
52+
//{
53+
// // Existing object is a ???
54+
55+
// return null;
56+
// //// Instantiate the component
57+
// //GameObject go = new GameObject();
58+
59+
// //// Add a SpatialFrame to it
60+
// //SpatialFrame frame = go.AddComponent<SpatialFrame>();
61+
62+
// //// Deserialize into the instance
63+
// //serializer.Populate(reader, frame);
64+
65+
// //// Update the game object name to match
66+
// //go.name = frame.Id;
67+
68+
// //// Return the frame
69+
// //return frame;
70+
//}
71+
72+
//public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
73+
//{
74+
// throw new NotImplementedException();
75+
//}
76+
}
77+
}

SpatialAlignment-Unity/Assets/SpatialAlignment/Persistence/Json/AlignmentStrategyConverter.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

SpatialAlignment-Unity/Assets/SpatialAlignment/Persistence/Json/JsonStore.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,12 @@ private JsonSerializer CreateSerializer()
5252
// Make pretty
5353
settings.Formatting = Formatting.Indented;
5454

55+
// Use custom contract resolver (handles Unity-specific instantiation)
56+
settings.ContractResolver = new SpatialContractResolver();
57+
5558
// Add converters
56-
settings.Converters.Add(new SpatialFrameConverter());
59+
// settings.Converters.Add(new AlignmentStrategyConverter());
60+
// settings.Converters.Add(new SpatialFrameConverter());
5761
settings.Converters.Add(new StringEnumConverter());
5862
settings.Converters.Add(new Vector3Converter());
5963

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
//
2+
// Copyright (c) Microsoft. All rights reserved.
3+
// Licensed under the MIT license.
4+
//
5+
// MIT License:
6+
// Permission is hereby granted, free of charge, to any person obtaining
7+
// a copy of this software and associated documentation files (the
8+
// "Software"), to deal in the Software without restriction, including
9+
// without limitation the rights to use, copy, modify, merge, publish,
10+
// distribute, sublicense, and/or sell copies of the Software, and to
11+
// permit persons to whom the Software is furnished to do so, subject to
12+
// the following conditions:
13+
//
14+
// The above copyright notice and this permission notice shall be
15+
// included in all copies or substantial portions of the Software.
16+
//
17+
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
18+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20+
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21+
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22+
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23+
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24+
//
25+
26+
using Newtonsoft.Json.Serialization;
27+
using System;
28+
using System.Collections.Generic;
29+
using System.Linq;
30+
using System.Reflection;
31+
using System.Text;
32+
using System.Threading.Tasks;
33+
using UnityEngine;
34+
35+
namespace Microsoft.SpatialAlignment.Persistence.Json
36+
{
37+
/// <summary>
38+
/// A Json.Net contract resolver with deserialization rules for
39+
/// spatial alignment classes.
40+
/// <remarks>
41+
/// Whenever this resolver creates a <see cref="SpatialFrame"/>,
42+
/// it sets that frame as the context for new objects to be
43+
/// created under it.
44+
/// </remarks>
45+
public class SpatialContractResolver : UnityContractResolver
46+
{
47+
#region Overridables / Event Triggers
48+
/// <inheritdoc />
49+
protected override Component CreateComponent(Type objectType)
50+
{
51+
// Is it a frame?
52+
bool isFrame = typeof(SpatialFrame).IsAssignableFrom(objectType);
53+
54+
// If it's a frame, the creation context should be a new object
55+
if (isFrame) { CreationContext = null; }
56+
57+
// Let the base create the component
58+
Component component = base.CreateComponent(objectType);
59+
60+
// Additional steps if this is a frame
61+
if (isFrame)
62+
{
63+
// Set the frame as the context for the next set of
64+
// behaviors to be attached to.
65+
CreationContext = component.gameObject;
66+
}
67+
68+
// Return the created component
69+
return component;
70+
}
71+
#endregion // Overridables / Event Triggers
72+
}
73+
}

SpatialAlignment-Unity/Assets/SpatialAlignment/Persistence/Json/SpatialContractResolver.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
//
2+
// Copyright (c) Microsoft. All rights reserved.
3+
// Licensed under the MIT license.
4+
//
5+
// MIT License:
6+
// Permission is hereby granted, free of charge, to any person obtaining
7+
// a copy of this software and associated documentation files (the
8+
// "Software"), to deal in the Software without restriction, including
9+
// without limitation the rights to use, copy, modify, merge, publish,
10+
// distribute, sublicense, and/or sell copies of the Software, and to
11+
// permit persons to whom the Software is furnished to do so, subject to
12+
// the following conditions:
13+
//
14+
// The above copyright notice and this permission notice shall be
15+
// included in all copies or substantial portions of the Software.
16+
//
17+
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
18+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20+
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21+
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22+
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23+
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24+
//
25+
26+
using Newtonsoft.Json.Serialization;
27+
using System;
28+
using System.Collections.Generic;
29+
using System.Linq;
30+
using System.Reflection;
31+
using System.Text;
32+
using System.Threading.Tasks;
33+
using UnityEngine;
34+
35+
namespace Microsoft.SpatialAlignment.Persistence.Json
36+
{
37+
/// <summary>
38+
/// A Json.Net contract resolver that knows how to instantiate Unity objects
39+
/// like <see cref="Component"/> and <see cref="MonoBehaviour"/>.
40+
/// </summary>
41+
/// <remarks>
42+
/// This resolver is necessary because in Unity we can't just create behaviors
43+
/// using their constructors, we must add them to game objects using
44+
/// <see cref="GameObject.AddComponent(Type)">AddComponent</see>.
45+
/// </remarks>
46+
public class UnityContractResolver : DefaultContractResolver
47+
{
48+
#region Member Variables
49+
private GameObject creationContext;
50+
#endregion // Member Variables
51+
52+
#region Overridables / Event Triggers
53+
/// <summary>
54+
/// Instantiates a Unity <see cref="Component"/> (or <see cref="MonoBehaviour"/>).
55+
/// </summary>
56+
/// <param name="objectType">
57+
/// The type of component to create.
58+
/// </param>
59+
/// <returns>
60+
/// The created component.
61+
/// </returns>
62+
protected virtual Component CreateComponent(Type objectType)
63+
{
64+
// Use the existing creation context if found
65+
// Otherwise, create a new GameObject to serve as the parent
66+
GameObject parent = (creationContext ?? new GameObject());
67+
68+
// Instantiate the component
69+
return parent.AddComponent(objectType);
70+
}
71+
#endregion // Overridables / Event Triggers
72+
73+
#region IContractResolver Overrides
74+
protected override JsonObjectContract CreateObjectContract(Type objectType)
75+
{
76+
77+
if (typeof(Component).IsAssignableFrom(objectType))
78+
{
79+
// Start with base contract
80+
var contract = base.CreateObjectContract(objectType);
81+
82+
// Override to instantiate the component
83+
contract.OverrideCreator = ((args) => CreateComponent(objectType));
84+
85+
// Return the new contract
86+
return contract;
87+
}
88+
else
89+
{
90+
// Just use the base contract.
91+
return base.CreateObjectContract(objectType);
92+
}
93+
}
94+
#endregion // IContractResolver Overrides
95+
96+
#region Public Properties
97+
/// <summary>
98+
/// Gets or sets the <see cref="GameObject"/> that will be used as the
99+
/// creation context.
100+
/// </summary>
101+
/// <remarks>
102+
/// If set, this <see cref="GameObject"/> will be used to instantiate
103+
/// components. Otherwise a new <see cref="GameObject"/> will be created
104+
/// for each new component.
105+
/// </remarks>
106+
public GameObject CreationContext { get => creationContext; set => creationContext = value; }
107+
#endregion // Public Properties
108+
}
109+
}

SpatialAlignment-Unity/Assets/SpatialAlignment/Persistence/Json/UnityContractResolver.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

SpatialAlignment-Unity/Assets/SpatialAlignment/SpatialFrame.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2424
//
2525

26+
using Microsoft.SpatialAlignment.Persistence.Json;
2627
using Newtonsoft.Json;
2728
using System;
2829
using System.Collections.Generic;
@@ -69,7 +70,18 @@ protected virtual void OnIdChanged()
6970
/// Gets the <see cref="IAlignmentStrategy"/> that is being used to align the frame.
7071
/// </summary>
7172
[DataMember]
72-
public virtual IAlignmentStrategy AlignmentStrategy { get => GetComponent<IAlignmentStrategy>(); }
73+
// [JsonProperty(ItemConverterType = typeof(AlignmentStrategyConverter))]
74+
public virtual IAlignmentStrategy AlignmentStrategy
75+
{
76+
get
77+
{
78+
return GetComponent<IAlignmentStrategy>();
79+
}
80+
set
81+
{
82+
var v = value;
83+
}
84+
}
7385

7486
/// <summary>
7587
/// Gets or sets a unique ID for the frame.

0 commit comments

Comments
 (0)