-1

I've been successfully writing and parsing back (recursively) my data using a custom JsonConverter, using this:

public override void WriteJson(JsonWriter writer, ManagedSubData value, JsonSerializer   serializer)
{
    skipOverMe = true;
    value.GrabAssetPath();
    writer.WriteValue(JsonConvert.SerializeObject(value));
}

The problem is, this gives me an unreadable Json full of backslashes everywhere. Now, I can use this instead of WriteValue, and it outputs a nice readable Json:

writer.WriteRawValue(JsonConvert.SerializeObject(value));

But when I try to read it back, it fails. reader.Value is now null, it's like it failed before even calling ReadJson

public override ManagedSubData ReadJson(JsonReader reader, Type objectType, ManagedSubData existingValue,
            bool hasExistingValue, JsonSerializer serializer)
{
    if (reader.TokenType == JsonToken.Null)
    {
        return null;
    }
            
//fails here since reader.Value is null
    JObject obj = JObject.Parse(reader.Value.ToString());
    ManagedSubData asset = ManagedDataHandler.GetSubDataFromGUID(obj["GUID"].ToString());
    if (asset == null)
    {
        asset = ScriptableObject.CreateInstance(objectType) as ManagedSubData;
#if UNITY_EDITOR
        if (!Application.isPlaying)
        {
            AssetDatabase.CreateAsset(asset, obj["assetPath"].ToString());
            AssetDatabase.SaveAssets();
        }
#endif
    }

    if (!asset.KeepPlayModeChanges)
    {
        JsonConvert.PopulateObject(reader.Value.ToString(), asset);
        asset.SetDirty();
    }

    return asset;
}

There are actual field values if I try to do reader.Read, it's just that the Value of the object itself is considered null.

Maybe I shouln't be trying to write Raw value? I am noticing that for every level of nesting, WriteValue adds additional slashes, but maybe it needs those to parse it back?

Does anyone have any ideas? We kinda need the Json to be readable and not full of garbage.

  • Can you show us what the data looks like and the error it generates? – Train Mar 29 '23 at 01:13
  • Its a Null Reference Exception because reader.Value is null. If I don't do WriteRawValue (using WriteValue instead), it looks like this { "testFloat1": 4, "testString": "FOO", "subdataTest": "{\r\n \"name\": \"asdasd\",\r\n \"weaponType\": \"Axe\",\r\n \"strings\": [\r\n \"hi\",\r\n \"bro\"\r\n ],\r\n \"vector\": {\r\n \"x\": 5.0,\r\n \"y\": 0.0,\r\n \"z\": 0.0\r\n },\r\n \"color\": {\r\n \"r\": 0.0,\r\n \"g\": 0.06425047,\r\n \"b\": 1.0,\r\n etc – Steven Goulet Mar 29 '23 at 01:22
  • I feel like I may be missing a setting somewhere to allow it to read it raw – Steven Goulet Mar 29 '23 at 01:23
  • Why do you need a custom serializer? I never heard that anybody had problems to serialze. The problem usually is to deserialzie Just use JsonConvert.SerializeObject(value). – Serge Mar 29 '23 at 11:35
  • You need Custom Serializer for things that can't be serialized on their own. This is the case for most unity objects Ex. there are custom serializers on the internet for Vector3, Color, and so on. In my case, ManagedSubData is a ScriptableObject – Steven Goulet Mar 29 '23 at 11:45
  • Pls post the object and class that you need to serialize, without this nobody will be able to help you. – Serge Mar 29 '23 at 11:51

1 Answers1

0

I think the main problem is that you don't really understand the difference between WriteRawValue and WriteValue, they are not the same thing and there is a reason why using WriteValue give you a string with escape instead of a clean json.

Take a look here: Is there an equivalent for JRaw in System.Text.Json

You want to use WriteRawValue only when your string is already a json object, but I think in your specific scenario it is better to just create an object of your json data and actually serialize it.

EDIT. Example based on your possible json

YourJsonObject.cs

[Serializable]
public class YourJsonObject {
   private float testFloat1;
   private string testString;
   private ComplexObject subdataTest;
   etc...
}

ComplexObject.cs

[Serializable]
public class ComplexObject {
    private string name;
    etc...
}

PS. Since you need to serialize Unity complex object like ScriptableObject you should use Unity3d default serializer

https://docs.unity3d.com/2021.2/Documentation/Manual/JSONSerialization.html

Warning: The JSON Serializer API supports MonoBehaviour and ScriptableObject subclasses as well as plain structs and classes. However, when deserializing JSON into subclasses of MonoBehaviour or ScriptableObject, you must use the FromJsonOverwrite method. If you try to use FromJson, Unity throws an exception because this behavior is not supported.

LiefLayer
  • 977
  • 1
  • 12
  • 29
  • How would I go on about doing this ? – Steven Goulet Mar 29 '23 at 12:50
  • Just create a Simple serializable C# class that will reproduce your json structure (if necessary make multiple classes) and pass it to your serializer... I'll edit my answer in a minute with an example – LiefLayer Mar 29 '23 at 12:53
  • My ComplexObject is derived from ScriptableObject which is an unity object (and needs to be) though – Steven Goulet Mar 29 '23 at 13:05
  • @StevenGoulet you should be able to do that with Unity3d default serializer https://docs.unity3d.com/2021.2/Documentation/Manual/JSONSerialization.html https://stackoverflow.com/questions/52377939/how-do-i-serialize-scriptableobjects – LiefLayer Mar 29 '23 at 13:09
  • Negative. The default Unity Json serializer is trash for many reasons, is extremely specific, can't do it tried it. If you try to serialize something like classA.classB.classC with all of them being c# classes it works but in my case, I need the custom converter to "link" the Scriptables if that makes sense. But maybe using Raw value is the wrong approach? This may sound stupid but maybe there is a way with Json.net to not output those backslashes (I was able to remove the \r and \n, only the \ remain). I don't care if the Json is ugly looking as long as it can be "beautified" online. – Steven Goulet Mar 29 '23 at 13:17
  • Unity Json serializer is not trash. I used it in my project and it works. There are some limitation of course but also some advantages (ScriptableObject for example). Like in the .net version there are some advantages but also some limitations. I think using the raw data in your case is wrong because you don't need to serialize your json string as a string variable. In your question you need to be more specific if you want more help at this point. – LiefLayer Mar 29 '23 at 13:25