Skip to main content
Announcements
Qlik Connect 2025: 3 days of full immersion in data, analytics, and AI. May 13-15 | Orlando, FL: Learn More
cancel
Showing results for 
Search instead for 
Did you mean: 
andreas-hellquist-stratsys
Partner - Contributor II
Partner - Contributor II

JsonDeserialization error

Hi, 

I get below errror when trying to deserialize table data.

Property "qDimensionInfo" accessed as System.Collections.Generic.IEnumerable`1[[Qlik.Sense.Client.Visualizations.HyperCubeDimensionq, Qlik.Sense.Client, Version=16.4.0.0]] previously interpreted as System.Collections.Generic.List`1[[Qlik.Engine.NxDimensionInfo, Qlik.Engine, Version=16.4.0.0]]

 

Our partner upgraded to a new QlikSense version a week or so ago to May SR1 (don’t know if that is correctly notation) but no major release of .NET SDK lately so I guess I am missing something else.

Labels (2)
1 Solution

Accepted Solutions
Øystein_Kolsrud
Employee
Employee

This type of errors occur when a property of a class derived from the abstract structure class is deserialized with two different types. In this case, the dimensions have been deserialized as a list of "NxDimensionInfo", but the hypercube is then accessed through a client class which tries to interpret them as the client extension class "HyperCubeDimensionq". It tries to do an up-cast of the type, which fails.

Here is an example that illustrates how to end up in such a situation:

var o = app.GetObject<Table>(objId);
var tableCube = o.Properties.HyperCubeDef;        // Get table cube
var engineCube = tableCube.As<HyperCubeDef>();    // Interpret as engine cube
Console.WriteLine(engineCube.Dimensions.Count()); // Count engine cubes
Console.WriteLine(tableCube.Dimensions.Count());  // Count table cubes

During the first call to "Dimensions", the access is performed through the variable "engineCube". In this case, the type of the property "Dimensions" is "IEnumerable<NxDimension>". The data must be deserialized to an explicit type, not just an interface, and by default, the type "List" is used. So the dimensions are in fact deserialized to "List<NxDimension>".

Then during the second call, the dimensions are accessed through the variable "tableCube" for which the property "Dimensions" has the type "IEnumerable<TableHyperCubeDimensionDef>". But that property has now already been deserialized as "List<NxDimension>" which is incompatible with this new type, so the error is thrown. Note that it all works fine if you switch the order of the two counts. It's fine to down-cast a "TableHyperCubeDimensionDef" to "NxDimension", but you can't up-cast an "NxDimension" to a "TableHyperCubeDimensionDef".

This an unfortunate limitation with the abstract structure concept, but there is a pretty simple workaround. Simply do a clone of the object, that way you will get a copy that you can deserialize in a new way. In the above example, one could for instance use "CloneAs" instead of just "As" when setting the "engineCube" variable like this:

var o = app.GetObject<Table>(objId);                 
var tableCube = o.Properties.HyperCubeDef;          // Get table cube
var engineCube = tableCube.CloneAs<HyperCubeDef>(); // Clone as engine cube
Console.WriteLine(engineCube.Dimensions.Count());   // Count engine cubes
Console.WriteLine(tableCube.Dimensions.Count());    // Count table cubes

 More about the concept of abstract structure in the .NET SDK can be found here:

https://help.qlik.com/en-US/sense-developer/February2023/Subsystems/NetSDKAPI/Content/Sense_NetSDKAP...

View solution in original post

2 Replies
Øystein_Kolsrud
Employee
Employee

This type of errors occur when a property of a class derived from the abstract structure class is deserialized with two different types. In this case, the dimensions have been deserialized as a list of "NxDimensionInfo", but the hypercube is then accessed through a client class which tries to interpret them as the client extension class "HyperCubeDimensionq". It tries to do an up-cast of the type, which fails.

Here is an example that illustrates how to end up in such a situation:

var o = app.GetObject<Table>(objId);
var tableCube = o.Properties.HyperCubeDef;        // Get table cube
var engineCube = tableCube.As<HyperCubeDef>();    // Interpret as engine cube
Console.WriteLine(engineCube.Dimensions.Count()); // Count engine cubes
Console.WriteLine(tableCube.Dimensions.Count());  // Count table cubes

During the first call to "Dimensions", the access is performed through the variable "engineCube". In this case, the type of the property "Dimensions" is "IEnumerable<NxDimension>". The data must be deserialized to an explicit type, not just an interface, and by default, the type "List" is used. So the dimensions are in fact deserialized to "List<NxDimension>".

Then during the second call, the dimensions are accessed through the variable "tableCube" for which the property "Dimensions" has the type "IEnumerable<TableHyperCubeDimensionDef>". But that property has now already been deserialized as "List<NxDimension>" which is incompatible with this new type, so the error is thrown. Note that it all works fine if you switch the order of the two counts. It's fine to down-cast a "TableHyperCubeDimensionDef" to "NxDimension", but you can't up-cast an "NxDimension" to a "TableHyperCubeDimensionDef".

This an unfortunate limitation with the abstract structure concept, but there is a pretty simple workaround. Simply do a clone of the object, that way you will get a copy that you can deserialize in a new way. In the above example, one could for instance use "CloneAs" instead of just "As" when setting the "engineCube" variable like this:

var o = app.GetObject<Table>(objId);                 
var tableCube = o.Properties.HyperCubeDef;          // Get table cube
var engineCube = tableCube.CloneAs<HyperCubeDef>(); // Clone as engine cube
Console.WriteLine(engineCube.Dimensions.Count());   // Count engine cubes
Console.WriteLine(tableCube.Dimensions.Count());    // Count table cubes

 More about the concept of abstract structure in the .NET SDK can be found here:

https://help.qlik.com/en-US/sense-developer/February2023/Subsystems/NetSDKAPI/Content/Sense_NetSDKAP...

andreas-hellquist-stratsys
Partner - Contributor II
Partner - Contributor II
Author

Thank you for the explanation 👍