0

I'm working on writing a .Net Standard library for working with the UptimeRobot API. I've found an endpoint that sometimes returns an array of int and sometimes returns a single 0.

The field I'm working with is monitors.

{
  "stat": "ok",
  "pagination": {
    "offset": 0,
    "limit": 50,
    "total": 2
  },
  "psps": [
    {
      "id": 2345678,
      "friendly_name": "Full Status",
      "monitors": 0,
      "sort": 1,
      "status": 1,
      "standard_url": "https://stats.uptimerobot.com/xxxxxx",
      "custom_url": ""
    },
    {
      "id": 123456,
      "friendly_name": "Filtered Status",
      "monitors": [
        783210435,
        783210481
      ],
      "sort": 1,
      "status": 1,
      "standard_url": "https://stats.uptimerobot.com/xxxxxx",
      "custom_url": ""
    }
  ]
}

This is my model:

using Newtonsoft.Json;
using System.Collections.Generic;
using SharpenUp.Common.Types;
using System.Diagnostics.CodeAnalysis;

namespace SharpenUp.Common.Models.PublicStatusPages
{
    public class PublicStatusPage
    {
        [ExcludeFromCodeCoverage]
        [JsonProperty( PropertyName = "id" )]
        public int Id { get; set; }

        [JsonProperty( PropertyName = "friendly_name" )]
        public string Name { get; set; }

        [JsonProperty( PropertyName = "monitors" )]
        public List<int> Monitors { get; set; }

        [JsonProperty( PropertyName = "sort" )]
        public int Sort { get; set; }

        [JsonProperty( PropertyName = "status" )]
        public PublicStatusPageStatusType Status { get; set; }

        [JsonProperty( PropertyName = "standard_url" )]
        public string StandardURL { get; set; }

        [JsonProperty( PropertyName = "custom_url" )]
        public string CustomURL { get; set; }
    }
}

The Monitors object will parse if I limit my query to only the result with the array, but fails if I try to bring in the other.

Any ideas? I'm not even 100% certain what wording to use to try and figure this out.

Ian
  • 48
  • 1
  • 8
  • 1
    Add a converter to check if a single 0 is returned and add that to a list and return the default for everything else. – Nkosi Feb 25 '20 at 23:56

1 Answers1

0

You could use a Converter which converts cases where there is only a single item to List. For example, considering the following converter.

class SingleOrArrayConverter<T> : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(List<T>));
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
if (token.Type == JTokenType.Array)
{
return token.ToObject<List<T>>();
}
return new List<T> { token.ToObject<T>() };
}

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

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

You could now decorate your Monitors property with JsonConverter attribute as

[JsonConverter(typeof(SingleOrArrayConverter<int>))]
[JsonProperty( PropertyName = "monitors" )]
public List<int> Monitors { get; set; }

This would allow you to deserialize your Json correctly.

Sample Output

enter image description here

Anu Viswan
  • 17,797
  • 2
  • 22
  • 51