Is it possible to get the properties of JsonReader before reading?

Viewed 23

I am stuck at a problem with this, my current base API class implements getting an object from an API like this:

HttpResponceMessage GetResponce(string path) => Task.Run(async() => await client.GetAsync(path)); 

T GetTFromRequest<T>(string path, JsonConverter[] converters) => 
    Task.Run(async() => await GetResponce(path).Content.ReadAsAsync<T>(converters); // Converters gets put into a new JsonMediaTypeFormatter

These are used in other classes to make quick methods. Class Example:

public class ExampleAPI : BaseAPI
{
    private static readonly JsonConverter[] converters = new[] { new RecordCoverter() };

    public string APIKey { get; set; }

    public ExampleData GetExampleData(/* params here such as string apiKey */) =>
        GetTFromRequset<ExampleData>($"examplepath?key={APIKey}", converters);
}

Example data would be something like this:

{
    "success":true,
    "records":[
        {
            "Foo":"Bar",
            "Data":"Dahta"
        }
    ]
}

So the classes would look like this:

public class RecordConverter : JsonConverter
{
    public override bool CanConvert(Type objectType) => objectType == typeof(IRecord);

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

public interface IRecord {}

public class ExampleData
{
    public bool success { get; set; } = true;
    public IRecord[] records { get; set; } = new[] {};
}

public class DataRecord : IRecord
{
    public string Foo { get; set; }
    public string Data { get; set; }
}

public class FaltyRecord : IRecord
{
    public string Bar { get; set; }
    public string Dahta { get; set; }
}

The issue that keeps arising that I can't figure out if the objects in "records" is FaltyRecords or DataRecords without doing reader.Read() which would just throw off just being about to put the following into RecordConverter:

if(reader.NextProperties().All(x => DataRecordProps.Contains(x))) 
    return serializer.Deserialize<DataExample>(reader);
if(reader.NextProperties().All(x => FaltyRecordProps.Contains(x)))
    return serializer.Deserialize<FaltyRecord>(reader);
if(...)
    return ...;

I know that in XmlReader there's the method GetSubtree() so I can do var propReader = reader.GetSubtree(); then use propReader as much as I want and just do retrun (IRecord[])serializer.Deserialize(reader);. I also see using JObject a lot but I don't see a JObject(reader) method.

1 Answers

Use JObject.Load(reader) method.

var jObj = JObject.Load(reader);
var properties = jObj.Properties();
// code here to find the type
return jObj.ToObject(type);
Related