(EDIT: The JSON object is a dictionary, and can be deserialized natively into an object that implements IDictionary. See the duplicate question post.)
I am deserializing JSON data from an API and the format of the return data is a little odd (to me). I haven't seen it structured like this before, and I am hoping there is a way to deserialize this without building a custom converter.
{
    "1000" : {
        "id" : 1000, 
        "prop2" : "value2", 
        "prop3" : "value3"
    }, 
    "1001" : {
        "id" : 1001, 
        "prop2" : "value2", 
        "prop3" : "value3"
    }, 
    "XXXX" : {
        "id" : XXXX, 
        "prop2" : "value2", 
        "prop3" : "value3"
    }
}
As you can see from the example, rather than an array of objects, it is an object where the property name is the string value of the sub-object's ID. This is from HubSpot, and you can see the API doc here: https://developers.hubspot.com/docs/methods/contacts/get_batch_by_email
I've started down the road of creating a custom JSON converter which I am not very far along with yet, I just started testing. (It's not often that I need to do this, and I have to re-learn it each time.)
[JsonConverter(typeof(EmailContactConverter))]
internal class EmailContactListResponse
{
    public IEnumerable<ContactResponse> Contacts { get; set; }
}
class EmailContactConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException("Not implemented yet");
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
        {
            return string.Empty;
        }
        else if (reader.TokenType == JsonToken.String)
        {
            return serializer.Deserialize(reader, objectType);
        }
        else
        {
            JObject obj = JObject.Load(reader);
            var list = new List<ContactResponse>();
            return list;
        }
    }
    public override bool CanWrite
    {
        get { return false; }
    }
    public override bool CanConvert(Type objectType)
    {
        return false;
    }
}
Is there a way to represent this with built-in NewtonSoft JSON attributes or mapping? Or am I right to continue down the custom converter route?
