Expose Speckle.Newtonsoft in Grasshopper as a node

Seeing as JSwan is out of support, and Speckle loads its own version of Newtonsoft into GH, it might be a good “two birds, one stone” thing to have XML > Speckle and JSON > Speckle nodes.

I whipped up an example that uses some of our internal patterns that worked, but I think it belongs in the speckle extension so we don’t get dependency hell. I’d contribute it but I know the converters are getting a rejig, so currently it’s just a suggestion - POC worked pretty well!

Is your M2S node a simple c# wrapper?

It just steps through any JSON file provided and converts it all to Base - I’ll drop it as a snippet below as its fairly simple:

public static class Converters
{
    static Base GetBase(JToken token)
    {
        Base root;

        if (token.Type == JTokenType.Object)
        {
            root = new Base();

            foreach (JProperty property in token.Children<JProperty>())
            {
                string propertyName = property.Name;

                if (property.Value.Type == JTokenType.Object || property.Value.Type == JTokenType.Array)
                {
                    Base intermediateBase = GetBase(property.Value);

                    if (intermediateBase is Collection c)
                    {
                        root[propertyName] = c;
                    }
                    else
                    {
                        root[propertyName] = intermediateBase;
                    }
                }
                else
                {
                    root[propertyName] = property.Value.ToObject<object>();
                }
            }
        }
        else if (token.Type == JTokenType.Array)
        {
            Collection g = new Speckle.Core.Models.Collection();

            foreach (JToken item in token.Children())
            {
                g.elements.Add(GetBase(item));
            }
            root = g;
        }
        else
        {
            //edge case for things like arrays of strings

            root = new Base();

            switch (token.Type)
            {
                case JTokenType.String:
                    root["string"] = (string?)token ?? "";
                    break;
                case JTokenType.Boolean:
                    root["bool"] = (bool)token;
                    break;
                case JTokenType.Integer:
                    root["int"] = (int)token;
                    break;
                case JTokenType.Float:
                    root["float"] = (double)token;
                    break;
                case JTokenType.None:
                    root["null"] = null;
                    break;
                default:
                    root["object"] = token.ToObject<object>();
                    break;
            }
        }
        return root;
    }

    public static Base FromJSON(this Stream stream)
    {
        using JsonTextReader reader = new(new StreamReader(stream));
        return GetBase(JObject.Load(reader));
    }
}

Contributions are always welcome, GH isn’t on the critical path of connector refactoring right now.

1 Like

All good I’ll keep this one on the back burner in that case!