0

I'm receiving varying JSONs with nested json objects and json arrays to C# app, and parsing them using Newtonsoft.JSON. I'm sending this data to MATLAB app, and want to send it as plain as I can for the MATLAB to parse the .NET types to MATLAB correctly.

For that, I convert the JObject's to Dictionary<string, dynamic>. I use dynamic so that the MATLAB will get int, double, String instead of object always.

I also convert the JArray's to object[] (using similar ToObject() function as in that thread).

What I'm missing is a way to fully convert JArray's to double[], int[,]. etc, if they are actually of that type. This will enable the MATLAB to parse them to MATLAB's double, int32, etc correctly.

Is there a way of achieving this? Can it also be applied to multidimensional arrays?

Clarification: If I'm getting arrays of strings, I don't mind leaving it object[]. I mostly care for numeric multidimensional arrays.

EDIT: As MATLAB prefer jagged arrays over multidimensional, so do I :)

Existing Code:

I currently expose the following Struct-like type to MATLAB, as it's not possible to marshal MATLAB structs to C#:

[JsonConverter(typeof(StructConverter))]
public class Struct
{

    [JsonExtensionData]
    Dictionary<string, dynamic> dict;

    public Struct() => dict = new Dictionary<string, dynamic>();
    public Struct(Dictionary<string, dynamic> d) => dict = d;
    public string[] GetKeys() => dict.Keys.ToArray();
    public void Set(string key, dynamic value) => dict[key] = value;
    public void SetVector(string key, int[] value) => dict[key] = value;
    public void SetVector(string key, double[] value) => dict[key] = value;
    public dynamic Get(string key) => dict[key];

}

Where StructConverter is my current converter:

public class StructConverter : JsonConverter
{

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        return ReadValue(reader);
    }

    private dynamic ReadValue(JsonReader reader)
    {
        switch (reader.TokenType)
        {
            case JsonToken.StartObject:
                return ReadObject(reader);
            case JsonToken.StartArray:
                return ReadArray(reader);
            default:
                return reader.Value;
        }
    }

    private dynamic ReadObject(JsonReader reader)
    {
        MatNet.Struct s = new MatNet.Struct();
        while (reader.Read())
        {
            switch (reader.TokenType)
            {
                case JsonToken.PropertyName:
                    string propName = reader.Value.ToString();
                    if (!reader.Read()) throw new Exception("Unexpected end when reading ExpandoObject.");
                    s.Set(propName, ReadValue(reader));
                    break;
                case JsonToken.Comment:
                    break;
                case JsonToken.EndObject:
                    return s;
            }
        }
        throw new Exception("Unexpected end when reading ExpandoObject.");
    }

    private dynamic ReadArray(JsonReader reader)
    {
        List<dynamic> list = new List<dynamic>();
        while (reader.Read())
        {
            switch (reader.TokenType)
            {
                case JsonToken.Comment:
                    break;
                default:
                    list.Add(ReadValue(reader));
                    break;
                case JsonToken.EndArray:
                    return list.ToArray();
            }
        }
        throw new Exception("Unexpected end when reading ExpandoObject.");
    }

}

I'm able to serialize and deserialize the following, but the arrays are of object[] instead of int[], string[] and double[]:

    var d = new MatNet.Struct();
    d.Set("a", new int[] { 1, 2, 4, 8, 16 });
    d.Set("b", new string[] { "qwer", "tyui", "asdf", "ghjk" });
    d.Set("c", new double[,] { {1, 3}, {2, 4}, {5, 7}, {6, 8} });
    d.Set("d", new MatNet.Struct());
    var json = JsonConvert.SerializeObject(d);
    dynamic x = JsonConvert.DeserializeObject<MatNet.Struct>(json);
galah92
  • 3,621
  • 2
  • 29
  • 55
  • The matlab library functions for parsing string a much better than c#. So I would look for a method in matlab to convert json to arrays. – jdweng Jan 11 '18 at 13:47
  • The problem with that is opposite - MALTAB has looser sense of arrays, as `1` is `double` but also `[1]`, meaning I can't marshal `[1]` from MATLAB to C# correctly. I also need to ability to access a specific string from the received JSON in C# before handing it to MATLAB, so it make sense to parse it in C#. – galah92 Jan 11 '18 at 13:51
  • It would probably help to see some existing code (see [MCVE]) so we can run test cases to identify a solution. – Wolfie Jan 11 '18 at 14:50
  • You're right, I've added my code. – galah92 Jan 11 '18 at 15:30
  • No reason going from Matlab to c# should be an issue for arrays. – jdweng Jan 11 '18 at 17:52
  • 1
    But it is. if my `Set()` method which MATLAB uses has `object`/`dynamic` parameter, there is no way to pass `[1]`. There is also no way to pass `[[1, 2]]`. – galah92 Jan 11 '18 at 18:18

0 Answers0