Created
June 6, 2023 17:21
-
-
Save CharlieHess/92f18b9dbb2723fcc8a0fe76df18744e to your computer and use it in GitHub Desktop.
Flexible serialization using SOs and DTOs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[Serializable] | |
[JsonObject(MemberSerialization.OptIn)] | |
public class Item { | |
[JsonProperty] | |
public string Id; | |
// ... other stuff | |
/// <summary> | |
/// This only needs to be implemented for *mutable* serialized properties. | |
/// Properties that already exist on the ScriptableObject will be cloned | |
/// during deserialization and are never persisted. | |
/// </summary> | |
public virtual void PopulateFromJson(JObject json) { | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[CreateAssetMenu(fileName = "Item", menuName = "Scriptable Objects/Items/Item")] | |
public class ItemAsset : ScriptableObject, IItemAsset { | |
// ... all your properties | |
public virtual Item CreateItem() { | |
return new Item { | |
// copy properties from the SO into the instance | |
}; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using Newtonsoft.Json; | |
using Newtonsoft.Json.Linq; | |
using Zenject; | |
/// <summary> | |
/// Items by default only serialize their ID, which we can map to a scriptable | |
/// object in the ItemRegistry. Any mutable properties beyond that template | |
/// must be deserialized in Item.PopulateFromJson. | |
/// </summary> | |
public class ItemConverter : JsonConverter<Item> { | |
[Inject] protected readonly ItemRegistry _itemRegistry; | |
public override bool CanWrite => false; | |
public override Item ReadJson( | |
JsonReader reader, | |
Type objectType, | |
Item existingValue, | |
bool hasExistingValue, | |
JsonSerializer serializer | |
) { | |
var json = JObject.Load(reader); | |
var id = json["Id"].Value<string>(); | |
var newItem = _itemRegistry[id].CreateItem(); | |
newItem.PopulateFromJson(json); | |
return newItem; | |
} | |
public override void WriteJson(JsonWriter writer, Item value, JsonSerializer serializer) { | |
throw new NotImplementedException(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// A collection of all ItemAsset ScriptableObjects, keyed by their ID, which is also their filename. | |
/// </summary> | |
public class ItemRegistry { | |
protected Dictionary<string, ItemAsset> _registry; | |
public ItemAsset this[string id] => _registry.GetValueOrDefault(id); | |
// I use Zenject to populate this singleton, but you can just as easily use Resources.Load | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment