Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ReadJson not called

What I want to achieve. I have a class that has some properties/objects in it. I want to serialize only those objects which meet the CanConvert condition with my custom serializer, others should be handled defaultly.

Problem is that with [JsonConverter(typeof(UnityObjectConverter))] it serializes correctly but deserialization fails. Probably because I save only path to the object, not the whole object and when some internal check (which I don't get why) occurs than it fails and returns null, because the ReadJson is never called.

When I use Settings, it causes more problems to me, that it solves because it does not serialize the rest. I don't want to have serialization for the whole class, because that way it wouldn't be very universal since several objects inherit that class. The class itself is not abstract so there might be some objects using just the class. I would be really glad if someone could help. Thanks

 public class UnityObjectConverter : JsonConverter {

public override bool CanConvert(Type objectType) {
    Debug.Log(objectType.BaseType == typeof(UnityEngine.Object));
    return objectType.BaseType == typeof(UnityEngine.Object);
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
    Debug.Log("read");
    return UnityEditor.AssetDatabase.LoadAssetAtPath(reader.ReadAsString(), objectType);
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
    Debug.Log("write");
    var item = (UnityEngine.Object)value;
    writer.WriteValue(UnityEditor.AssetDatabase.GetAssetPath(item));
    writer.Flush();
}

public override bool CanRead {
    get {
        return true;
    }
}

public override bool CanWrite {
    get {
        return true;
    }
}
 }

Example of property

 /// <summary>
    /// GameObject if item is needed to be visualised
    /// </summary>
    [JsonConverter(typeof(UnityObjectConverter))]
    public GameObject gameObject { get { return _gameObject; } private set { _gameObject = value; } }
    protected GameObject _gameObject = null;

Example of de/serialization

public static void Add(Item i) {
        items.Add(i);
        if (!System.IO.File.Exists(Application.dataPath + DATA_PATH))
            System.IO.File.Create(Application.dataPath + DATA_PATH).Close();
        using (System.IO.StreamWriter sw = System.IO.File.CreateText(Application.dataPath + DATA_PATH)) {
            sw.Write(JsonConvert.SerializeObject(items));
        }
    }

static void Load() {
        items.Clear();
        Item[] it = JsonConvert.DeserializeObject<Item[]>(System.IO.File.ReadAllText(Application.dataPath + DATA_PATH));
        if (it != null)
            items.AddRange(it);
    }
like image 598
adsamcik Avatar asked Jun 16 '15 12:06

adsamcik


1 Answers

When I did this sort of thing, I created a JsonSerializerSettings object

 var settings = new JsonSerializerSettings
 {
     ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
     DefaultValueHandling = DefaultValueHandling.Ignore,
     NullValueHandling = NullValueHandling.Ignore
 };
 settings.Converters.Add(new Converter());

Then passed that into the deserializer

 var json = textReader.ReadToEnd();
 return JsonConvert.DeserializeObject<T>(json, settings);
like image 54
Richard June Avatar answered Oct 18 '22 03:10

Richard June