0

I'm getting JSON data like this from a third party API, which I cannot change:

{"ts":1234567890,"updates":[[4,104482,8209,2000000007,1462994403,"some text","some text again",{"from":"1337"}],[80,7,0],[7,2000000007,104481],[62,76706856,7]]}

I tried this code to deserialize it:

public class LongpollData
{
    public ulong Ts { get; set; }

    public List<Tuple<ApiEvent, int, ApiMask, ulong?, ulong?, string, string, FromInfo>> Updates { get; set; }

    public class FromInfo
    {
        string From { get; set; }
    }

    public enum ApiEvent
    {
        delete = 0,
        replace = 1,
        setMessageFlags = 2,
        resetMessageFlags = 3,
        newMessage = 4,
        readAllIn = 6,
        readAllOut = 7,
        friendIsOnline = 8,
        friendIsOffline = 9,
        chatChanged = 51,
        userIsTyping = 61,
        userIsTypingIn = 62,
        userMadeCall = 70,
        unreadMessagesCount = 80,
        notificationSettingsChanged = 144,
    }

    [Flags]
    public enum ApiMask
    {
        UNREAD = 1,
        OUTBOX = 2,
        REPLIED = 4,
        IMPORTANT = 8,
        CHAT = 16,
        FRIENDS = 32,
        SPAM = 64,
        DELЕTЕD = 128,
        FIXED = 256,
        MEDIA = 512,
    }
}

...
var UpdateData = JsonConvert.DeserializeObject<LongpollData>(webData);

but I'm getting an exception:

Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'System.Tuple8[VkKonekoBot.vkLongpollEvents+LongpollData+ApiEvent,System.Int32,VkKonekoBot.vkLongpollEvents+LongpollData+ApiMask,System.Nullable1[System.UInt64],System.Nullable`1[System.UInt64],System.String,System.String,VkKonekoBot.vkLongpollEvents+LongpollData+FromInfo]' because the type requires a JSON object (e.g. {\"name\":\"value\"}) to deserialize correctly.\r\nTo fix this error either change the JSON to a JSON object (e.g. {\"name\":\"value\"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.\r\nPath 'updates[0]', line 1, position 29.

What am I doing wrong?

Brian Rogers
  • 125,747
  • 31
  • 299
  • 300
NOiSY
  • 105
  • 1
  • 1
  • 5
  • and if Updates field is empty (seems like this: `..."updates":[]}`) is working correctly – NOiSY May 11 '16 at 22:12
  • Try to change the type of Updates to object[] – Gusman May 11 '16 at 22:13
  • wow, this works! but how i can convert `object[]` to `List>`? – NOiSY May 11 '16 at 22:25
  • Look at your model again, that tuple doesn't match the content of the Update field, you have an array of arrays of undetermined type of data, so that's the best you will get, you need then to inspect the content of the array and map it manually. – Gusman May 11 '16 at 22:29
  • Well, to be right, the best you can get is instead of `object[]` an `object[][]` – Gusman May 11 '16 at 22:29
  • Do you need all of the values in `updates`, or just a few? I notice that not all of the inner arrays have the same length in the JSON-- that is one problem that will have to be dealt with. Can you tell us more about what the data represents? – Brian Rogers May 11 '16 at 23:03
  • @BrianRogers i want parse data only like `[4,104482,8209,2000000007,1462994403,"some text","some text again",{"from":"1337"}]` but server also return data like `[80,7,0],[7,2000000007,104481],[62,76706856,7]` and now i don't want handle this data (maybe i do need it later) – NOiSY May 12 '16 at 02:12

1 Answers1

0

As noted by Gusman, in the comments the only direct option here is to deserialize the updates field as an object[][]. As a first step that at least gets the data into a form you can manipulate.

For instance, you can deserialize into this class:

class temp
{
    public long ts;
    public object[][] updates;
}

From there you would need to have some way to create instances of your Tuple or some other type from those arrays. For the text and numbers the conversion is as simple as unboxing values, for the complex type ({"from":"1337"}) you'll need to deal with the JSObject or convert it back to JSON and start again.

Not simple.

You could also use a custom deserializer class... see here for some pointers.

Community
  • 1
  • 1
Corey
  • 15,524
  • 2
  • 35
  • 68