3

I'm actually new to Web Api, so my question may sound a bit odd.

I have simple API to return historical information about price changes. My controller's action looks like this:

[HttpGet]
[Route("api/history/{id}/{size}")]
public async Task<IEnumerable<PriceHistoryRecordModel>> GetHistory(string id, Size size)

where PriceHistoryRecordModel is

[DataContract]
public class PriceHistoryRecordModel
{
    [DataMember]
    public DateTime Date { get; set; }

    [DataMember]
    public double Value { get; set; }
}

However, the problem is - action returns JSON in following format

[{"Date":"2016-02-07T08:22:46.212Z","Value":17.48},{"Date":"2016-02-08T09:34:01.212Z","Value":18.37}]

but, due to specific client requirements to data format, I need my JSON to look this way

[[1238371200000,17.48],[1238457600000,18.37]]

So, I wonder

  • if there's a way to achieve such custom serialization?
  • can I wrap this custom serialization in an attribute and use it as an aspect?
2
  • 1
    Try changing your return type to double[]: public async Task<IEnumerable<double[]>> GetHistory(string id, Size size). And covert your datetime to a number by using DateTime.Millisecond Commented Mar 26, 2016 at 9:43
  • @KhanhTO Thanks, that worked and resolved the immediate problem. However, a question with custom serialization stays. Commented Mar 26, 2016 at 11:47

1 Answer 1

5

You can write a CustomConverter like this:

public class CustomCoverter : JsonConverter
    {
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            PriceHistoryRecordModel obj = value as PriceHistoryRecordModel;
            JToken t = JToken.FromObject(new double[] { obj.Date.Ticks, obj.Value });
            t.WriteTo(writer);
        }

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

        public override bool CanConvert(Type objectType)
        {
            return typeof(PriceHistoryRecordModel).IsAssignableFrom(objectType);
        }
    }

Specify that our class is serialized by this converter:

[JsonConverter(typeof(CustomCoverter))]
[DataContract]
public class PriceHistoryRecordModel
{
    [DataMember]
    public DateTime Date { get; set; }

    [DataMember]
    public double Value { get; set; }
}

It works, but it's kind of overhead if you only need this special treatment in this specific case.

In case you have many similar cases like this, you can have your classes implement a base class and use this converter for all these classes.

In this simple case, a quick solution is just to change your return type to double[]:

public async Task<IEnumerable<double[]>> GetHistory(string id, Size size)

And covert your datetime to a number by using DateTime.Ticks

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.