How to fix JsonConverter's "Unable to parse back Raw Value" error?

109 views Asked by At

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.

1

There are 1 answers

6
LiefLayer On

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.