1
  1. i have a json file like below as input parameters for Revit design automation:
const data = {
    ModelId: "dXJuOmFkc2sud2lwcHJvZDpmcy5maWxlOnZmLjNSTzhMWmtUVGVHM3p1M1FoNjRGM3c_dmVyc2lvbj0x",
    ElementIds: [{
        "UniqueId": "ca5762b5-0f46-4a2f-8599-1d1a5dd19a81-00024b8c"
    }, {
        "UniqueId": "91e18c07-1bae-4949-a093-e0a4552bb478-000241ea"
    }]
};
var file = new File([data], "inputParameters.json", {
    type: "application/json"
});
  1. "success" workitem except the below error message in report file:
[07/09/2022 03:36:41] Exception when parsing json file: Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'ProjectSchedule.InputCache' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
  1. my Revit plugin C# code as below:
    public static bool ImportFromCache(Application rvtApp, Document doc)
    {
        InputCache inputCache = InputCache.Parse("inputParameters.json");
    }
    internal class InputCache
    {
        public string ModelId { get; set; } = "";
        public string[] ElementIds { get; set; } = { };
        static public InputCache Parse(string jsonPath)
        {
            if (!File.Exists(jsonPath)) return new InputCache { ModelId = "", ElementIds = { } };
            string jsonContents = File.ReadAllText(jsonPath);
            return JsonConvert.DeserializeObject<InputCache>(jsonContents);
        }
    }
  1. i tried to fix it via below C# code:
    public static bool ImportFromCache(Application rvtApp, Document doc)
    {
        string jsonContents = File.ReadAllText("cache.json");
        var inputCache = JsonConvert.DeserializeObject<List<InputCache>>(jsonContents);
    }
    internal class InputCache
    {
        public string ModelId { get; set; } = "";
        public string[] ElementIds { get; set; } = { };
    }
  1. but "failedInstructions" workitem w/ below error message in report file:
[07/09/2022 05:02:16] Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: o. Path '', line 1, position 1.
Rahul Bhobe
  • 4,165
  • 4
  • 17
  • 32
bim2016
  • 105
  • 1
  • 10
  • it looks that Design Automation just downloaded the JSON file via a URL. Your addin code is parsing the file that you uploaded to the Cloud Storage. By looking at the C# code above, did you try `return JsonConvert.DeserializeObject(jsonContents)`? also you may try to change content of `ElementIds` to be `ElementIds: [ "ca5762b5-0f46-4a2f-8599-1d1a5dd19a81-00024b8c", "91e18c07-1bae-4949-a093-e0a4552bb478-000241ea"]` – Emma Zhu Jul 09 '22 at 14:53
  • I suggest that you debug your C# code deserializing the JSON file locally first where the errors can be easily identified and fixed. – Emma Zhu Jul 09 '22 at 15:04
  • right, json data format needs to be optimized, and good idea to debug addin locally, thanks Emma! – bim2016 Jul 09 '22 at 17:05

2 Answers2

1

There are 2 problems with your example.

First: You are saving the json data as an array but trying to deserialize as an object:

var file = new File([data], "inputParameters.json", {
    type: "application/json"
});

This explains the error you have:

Exception when parsing json file: Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'ProjectSchedule.InputCache' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.

To fix this, you can change your js code to not convert your data into an array or account for an array in your appbundle code.

A possible solution in js code:

var file = new File([JSON.stringify(data)], "inputParameters.json", {
    type: "text/plain"
});

Or change in appbundle code (removes the redundant square brackets):

string fileContents = File.ReadAllText("cache.json");
string jsonContents = fileContents.Substring(1, fileContents.Length-2);
var inputCache = JsonConvert.DeserializeObject<List<InputCache>>(jsonContents);

The second problem that you have not yet encountered with deserialization is explained in an earlier answer.

Rahul Bhobe
  • 4,165
  • 4
  • 17
  • 32
0

Your JSON data and the class object you are trying to deserialize to do not match. Your JSON data has a list of objects (ElementId) with each element id containing a field UniqueId. Where as your class InputCache expects only an array of strings. The fix would be to either change your json data format or the InputCache class structure.

Here is an example on .NET fiddle: https://dotnetfiddle.net/RfX20L

using System;
using Newtonsoft.Json;

public class Program
{
    internal class ElementId
    {
      public string UniqueId { get; set; }
    }

    internal class InputCache
    {
      public string ModelId { get; set; }
      public ElementId[] ElementIds { get; set; }
    }
    
    public static void Main()
    {
        var json = "{'ModelId':'dXJuOmFkc2sud2lwcHJvZDpmcy5maWxlOnZmLjNSTzhMWmtUVGVHM3p1M1FoNjRGM3c_dmVyc2lvbj0x','ElementIds':[{'UniqueId':'ca5762b5-0f46-4a2f-8599-1d1a5dd19a81-00024b8c'},{'UniqueId':'91e18c07-1bae-4949-a093-e0a4552bb478-000241ea'}]}";
        
        var obj = JsonConvert.DeserializeObject<InputCache>(json);
        
        foreach(var id in obj.ElementIds) {
            Console.WriteLine(id.UniqueId);
        }
        
    }
}
Rahul Bhobe
  • 4,165
  • 4
  • 17
  • 32
  • spot-on! thanks Rahul – bim2016 Jul 09 '22 at 17:09
  • wait a second, just tested after modifying add-in, works OK at dotnetfiddle.net but not in forge DA workitem, is it because add-in code is parsing the file uploaded to the Cloud Storage? well, i need to test add-in locally as suggested by Emma – bim2016 Jul 09 '22 at 18:30
  • The original problem with regards to "Cannot deserialize the current JSON array (e.g. [1,2,3])" will be solved with restructuring your class definition. But if you modified your code further than that and are running into other problems, you may post another question or reach out to `forge.help[at]autodesk[dot]com` – Rahul Bhobe Jul 09 '22 at 18:43
  • [07/09/2022 18:10:55] Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'ProjectSchedule.InputCache' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly. – bim2016 Jul 09 '22 at 18:45
  • Looks like it is the same error. Did you upload the new appbundle with new code and then patch the alias to the new version of your appbundle? – Rahul Bhobe Jul 09 '22 at 18:51
  • yes, i recreated appbundle and activity, my main code in add-in: string jsonContents = File.ReadAllText("cache.json"); var obj = JsonConvert.DeserializeObject(jsonContents); – bim2016 Jul 09 '22 at 19:02
  • [07/09/2022 18:56:20] To 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. – bim2016 Jul 09 '22 at 19:05
  • Could you post your entire new code and contents of `cache.json` somewhere and share again? – Rahul Bhobe Jul 09 '22 at 19:06
  • Is this the same error you have: https://dotnetfiddle.net/2BW72R – Rahul Bhobe Jul 09 '22 at 19:13
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/246302/discussion-between-bim2016-and-rahul-bhobe). – bim2016 Jul 09 '22 at 19:18