-1

After days searching I have finally decided to come from help because every solution I've found is not working.

Basically, I'm creating an TCP/IP server that receives a Json string with the name of the instruction to perform and the parameters of the function, for example: ["Nameofinstruction",{"dx":"4000"},{"dy":"160"},{"dz":"120"},{"mat":"test_material"}], but the name of the function and the parameters will be different each time so I need to add the different fields of the string to a dictionary. So far I have tried different things, the one that worked best being this, but I still get some errors, which I don't get if I use a simple string.

The class that deserializes the data is this one:

public class InstructionProc
{
    
    [JsonConverter(typeof(InstructionConverter))]
    public class ArrivingMessage
    {
        public ArrivingMessage()
        {
            arguments = new Dictionary<string, dynamic>();
        }

        public Dictionary<string, dynamic> arguments { get; set; }
    }

    public class InstructionConverter : JsonConverter
    {

        public override bool CanConvert(Type objectType)
        {
                return objectType == typeof(ArrivingMessage);                
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            var instruction = value as ArrivingMessage;

            foreach (var item in instruction.arguments)
            {
                writer.WritePropertyName(item.Key);
                writer.WriteValue(item.Value);
            }

            writer.WriteEndObject();
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            var instruction = existingValue as ArrivingMessage ?? new ArrivingMessage();               
            while (reader.Read())
            {
                if (reader.TokenType == JsonToken.EndObject) continue;                    
                var path = reader.Path;
                var val = reader.ReadAsString();                 
                instruction.arguments.Add(path, val);
            }
            
            return instruction;
        }
    }
}

So far what is always giving me problems is whatever operation involving the JsonReader reader. Also, this class is executed on a thread spawned whenever a new client connects to the server. Last, the error I get is always

Exception thrown: 'System.Threading.ThreadAbortException' in Newtonsoft.Json.dll

I am aware that this has something to do with my program being multithread, but as I said if I send a simple string and print it on the same thread as this class is executing, I don't have any problems, so I should lock something that I don't know of here.

  • Does this answer your question? [json deserialization to C# with dynamic keys](https://stackoverflow.com/questions/65727513/json-deserialization-to-c-sharp-with-dynamic-keys) – Charlieface Jul 19 '22 at 12:47
  • Just declare it like this `class Root { public Dictionary Nameofinstruction; }` then deserialize it `JsonConvert.DeserializeObject(yourJson)` – Charlieface Jul 19 '22 at 12:48
  • I think this is close to what you are describing. It's two steps. First use one consistent part of the message to determine what type the rest is, and then when you know the type, deserialize the rest. https://stackoverflow.com/questions/38679972/determine-type-during-json-deserialize – Scott Hannen Jul 19 '22 at 13:00
  • Are you able to specify the object's structure once you know the name of the instruction? Then you could deserialize to a `JArray` first, inspect the first element and then convert the remaining parameters to an object based on the instruction. – derpirscher Jul 19 '22 at 13:20
  • And where is the `reader` created you pass to `ReadJson` – derpirscher Jul 19 '22 at 13:42
  • Can you post an actual JSON document? What you posted looks like a fragment. I can't write or test anything if I'm unsure of the format. – Scott Hannen Jul 19 '22 at 17:33
  • If you have control over the JSON, I'd start by changing that. Perhaps something like ```{ "Nameofinstruction": "xyz", "dx": "4000" , "dy": "160" , "dz": "120" , "mat": "test_material" }``` After that the rest gets easier. – Scott Hannen Jul 19 '22 at 17:40

1 Answers1

0

try this

   string json = "[\"Nameofinstruction\",{\"dx\":\"4000\"},{\"dy\":\"160\"},{\"dz\":\"120\"},{\"mat\":\"test_material\"}]";

    var jsonParsed = JArray.Parse(json);

    Dictionary<string, string> data = jsonParsed.OfType<JObject>().Properties()
                                       .ToDictionary(p => p.Name, p => p.Value.ToString());
Serge
  • 40,935
  • 4
  • 18
  • 45
  • After trying that, I still get the same Thread Abort error. Looking into the methods, the JArray.Parse boils down to another function with the "reader", which is what seems to be causing the problem in every solution. Note that just before the var jsonParsed, if I try to print the json string I get no errors, no matter the quantity of threads I use – Ángel Martínez Jul 21 '22 at 06:56
  • @ÁngelMartínez I am sorry but what are you talking about? Where could you see a json reader or threads in my code? You should just copy past my code. – Serge Jul 21 '22 at 11:19
  • I'm sorry, the threading error I was mentioning was an underlying error I did not noticed when I was trying to solve this. Your solution seems to work perfectly fine, thanks for the help – Ángel Martínez Jul 28 '22 at 07:59