Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I am programming against a third party API which returns JSON data, but the format can be a little strange. Certain properties can either be an object (which contains an Id property), or a string (which is the Id of the object). For example, both of the following are valid:

{
    ChildObject: 'childobjectkey1'
}

and

{
    ChildObject: {
        Id: 'childobjectkey1',
        // (other properties)
    }
}

I'm trying to deserialize this using JSON.net into a strongly typed class, but haven't had much luck so far. My best idea was to serialise it to two properties, one a string and the other an object, and to use a custom JsonConverter for each to allow for the variable behaviour:

public abstract class BaseEntity
{
    public string Id { get; set; }
}

public class ChildObject : BaseEntity { }

public class MyObject
{
    [JsonProperty("ChildObject")]
    [JsonConverter(typeof(MyCustomIdConverter))]
    public string ChildObjectId { get; set; }

    [JsonProperty("ChildObject")]
    [JsonConverter(typeof(MyCustomObjectConverter))]
    public ChildObject ChildObject { get; set; }
}

However, setting the JsonProperty attribute on two properties with the same PropertyName causes the exception:

Newtonsoft.Json.JsonSerializationException: A member with the name 'ChildObject' already exists on '.....'. Use the JsonPropertyAttribute to specify another name.

I'm fairly sure the JsonConverter approach will work if I can get over this hurdle - I suspect the error is there because the JsonProperty attribute is used for Serialization as well as Deserialization. In this instance I have no interest in Serializing this class - it will only ever be used as the target for Deserialization.

I have no control over the remote end (it's a third party API), but I would like to be able to achieve this serialisation. I don't mind if it's using the approach I've started on, or one I've not thought of yet.

This question is also related, but there were no answers.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
276 views
Welcome To Ask or Share your Answers For Others

1 Answer

Try this (extend it with some thorough validation if you'll be using it in your code):

public class MyObject
{
    public ChildObject MyChildObject;
    public string MyChildObjectId;

    [JsonProperty("ChildObject")]
    public object ChildObject
    {
        get
        {
            return MyChildObject;
        }
        set
        {
            if (value is JObject)
            {
                MyChildObject = ((JToken)value).ToObject<ChildObject>();
                MyChildObjectId = MyChildObject.Id;
            }
            else
            {
                MyChildObjectId = value.ToString();
                MyChildObject = null;
            }
        }
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...