0

I'm receiving some data from a websocket which seems to be formatted as an Id with a Key Value Pair, which contains a string and some serialized JSON in the format: ID[type,json].

So for example:

42["login",{ "requestId":null,"loginToken":"fwadff","type":"display","clientGroup":null,"features":[],"force":true}]

So in this case: 42 is the Message ID login is the first string in the KVP indicating the type of JSON and the JSON is the second string

So the structure of the JSON-part will change and I need to use the first string to determine how I need to deserialize the JSON.

I could use some string function to isolate the KVP from the Message ID and then convert the KVP, but I can't use Split(',') as it will also split all of the elements from the JSON.

Since this seems like a generic structure, I thought there might be an easier way to do this which I don't probably know of.

What is the easiest way to convert this data into a KVP<string, string> or even KVP[string,dynamic] ?

This is what I have so far:

        string test = "42[\"login\",{ \"requestId\":null,\"loginToken\":\"fwadff\",\"type\":\"display\",\"clientGroup\":null,\"features\":[],\"force\":true}]";

        // EXTRACT KEY VALUE PAIR FROM STRING
        int startIndex = test.IndexOf('[');
        int endIndex = test.LastIndexOf(']');

        if (startIndex > -1 && endIndex > -1)
        {
            // EXTRACT KEY VALUE PAIR
            string kvp = test.Substring(startIndex, ((endIndex - startIndex)+1));
            string id = test.Substring(0, startIndex);

            Console.WriteLine(kvp);

            var result = kvp.Trim('[', ']')
            .Split(new[] { ',' }, 2);                
        }
Enigmativity
  • 113,464
  • 11
  • 89
  • 172
Cainnech
  • 439
  • 1
  • 5
  • 17
  • It's ALL JSON after the message ID. It's a JSON list, containing a string and an object. Do you have a JSON module handy? – Tim Roberts Aug 22 '23 at 03:25
  • I don't think it's all JSON after the message ID. It then would have to start with curly brackets after the message id wouldn't it? So 42{[login,...]} – Cainnech Aug 22 '23 at 03:29
  • Why would it have to start with curly brackets? The root in JSON can be a value, array, or object. If you remove the number, you can use System.Text.Json or JSON.NET to parse it. The differing array item types might require you to use the JSON readers directly to parse the array itself, but the full serializer could still be used for the object in the array. – ProgrammingLlama Aug 22 '23 at 03:37
  • I agree. The content does look like valid JSON. It is a heterogeneous array and is most likely going to need custom converters to handle the deserialization. – Akhilesh Bangalore Aug 22 '23 at 03:40
  • OP: if you are currently handling JSON in your program, which library are you using? – ProgrammingLlama Aug 22 '23 at 03:41
  • I'm using Newtonsoft.JSON – Cainnech Aug 22 '23 at 03:41
  • Couldn't you just use `IndexOf`, looking for the bracket (or even the first of `[` or `{`), and then use `Substring` to get the JSON. A Regex seems like overkill – Flydog57 Aug 22 '23 at 04:27
  • Anything within a JSON is valid JSON. `42` is a valid JSON document. `"hello"` is a valid JSON document. `[1,2,3]` is a valid JSON document. – Tim Roberts Aug 22 '23 at 18:22

1 Answers1

2

This works for me:

string test = "42[\"login\",{ \"requestId\":null,\"loginToken\":\"fwadff\",\"type\":\"display\",\"clientGroup\":null,\"features\":[],\"force\":true}]";
Regex regex = new Regex(@"\d+(\[.*\])$");

var output = (JArray)Newtonsoft.Json.JsonConvert.DeserializeObject(regex.Match(test).Groups[1].Value);

I get:

output

Enigmativity
  • 113,464
  • 11
  • 89
  • 172
  • 1
    I was going to suggest the same but with a slightly different regex "(?\d+)\[\"(?.*)\",{\s*(?.*)", this uses "named groups" making pulling out the values more transparent. – Dweeberly Aug 22 '23 at 03:47
  • This looks like it already deserialized the data from the JSON-part. But would this still work if the structure of the json was different? – Cainnech Aug 22 '23 at 03:49
  • @Cainnech If the structure is always a number followed by an array, then this will always work to provide that array as a `JArray`. – ProgrammingLlama Aug 22 '23 at 03:51
  • 1
    IndexOf and Substring seemingly an easier/more performant solution – Flydog57 Aug 22 '23 at 04:29
  • @Flydog57 - Possibly, but I'm not sure it's easier. That's subjective. I like the succinctness of Regex. I can read that easier. Performance would only be a consideration if this code is running over a massive number of lines. – Enigmativity Aug 22 '23 at 04:42
  • @Cainnech -- That's exactly what the DeserializeObject call does. That's the thing ALL of us have been trying to tell you. What you have is an ordinary JSON document with a numeric prefix. Get rid of the prefix, and you can use normal JSON tools to convert it to a structure. It will handle ANY valid JSON. This answer happens to use a regex to remove the prefix. I'd do it with IndexOf, but that's a personal choice. – Tim Roberts Aug 22 '23 at 18:26