How to deserialize a JSON symbol definition

349
2
Jump to solution
12-03-2020 02:02 PM
Douglas_DMeredith
New Contributor II

I am trying to create a CIMUniqueValueRenderer from a table that contains JSON symbol definitions. The symbol definitions in that table were pulled from a stylx file.

I am trying to use CIMSymbolReference.FromJson() to deserialize each symbol definition, but it keeps failing with the cryptic error "Wrong type name". The documentation here is failing me.

A typical JSON string looks like this: 

"{\"type\":\"CIMLineSymbol\",\"symbolLayers\":[{\"type\":\"CIMSolidStroke\",\"enable\":true,\"colorLocked\":true,\"primitiveName\":\"1.0\",\"capStyle\":\"Butt\",\"joinStyle\":\"Round\",\"lineStyle3D\":\"Strip\",\"miterLimit\":10,\"width\":0.43086614173228349,\"color\":{\"type\":\"CIMCMYKColor\",\"values\":[0,0,0,100,100]}}]}"

Can anyone tell me why CIMSymbolReference.FromJson() chokes on this?

Is there another way to get from a JSON symbol definition to a symbol I can use in a CIMUniqueValueClass?

Code excerpt:

await ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() => {

	using (Geodatabase geodatabase = new Geodatabase(DataHelper.connectionProperties)) {

		QueryDef cfQDef = new QueryDef {
			Tables = "CFSymbology",
			PostfixClause = "order by key"
		};

		using (RowCursor rowCursor = geodatabase.Evaluate(cfQDef, false)) {
			List<CIMUniqueValueClass> listUniqueValueClasses = new List<CIMUniqueValueClass>();
			while (rowCursor.MoveNext()) {
				using (Row row = rowCursor.Current) {
					Debug.WriteLine(row["key"].ToString());

					//create and load map unit
					var cf = new CF();
					cf.key = row["key"].ToString();
					cf.symbol = row["symbol"].ToString();

					//add it to our list
					cfs.Add(cf);

					//Create a "CIMUniqueValueClass" for the symbol and add it to the list of unique values.
					//This is what creates the mapping from map unit to color
					List<CIMUniqueValue> listUniqueValues = new List<CIMUniqueValue> {
							new CIMUniqueValue {
								FieldValues = new string[] { cf.key }
							}
					};
					CIMUniqueValueClass uniqueValueClass = new CIMUniqueValueClass {
						Editable = true,
						Label = cf.key,
						//Patch = PatchShape.Default,
						Patch = PatchShape.AreaPolygon,
						Symbol = CIMSymbolReference.FromJson(cf.symbol, null),
						Visible = true,
						Values = listUniqueValues.ToArray()
					};
					listUniqueValueClasses.Add(uniqueValueClass);

				}
			}

			//Create a list of CIMUniqueValueGroup
			CIMUniqueValueGroup uvg = new CIMUniqueValueGroup {
				Classes = listUniqueValueClasses.ToArray(),
			};
			List<CIMUniqueValueGroup> listUniqueValueGroups = new List<CIMUniqueValueGroup> { uvg };

			//Use the list to create the CIMUniqueValueRenderer
			DataHelper.cfRenderer = new CIMUniqueValueRenderer {
				UseDefaultSymbol = false,
				Groups = listUniqueValueGroups.ToArray(),
				Fields = new string[] { "key" }
			};

			//Set renderer in contactsandfaults layer. The try/catch is there because the first time through, this is called 
			//before the layer has been added to the map. We just ignore the error in that case.
			try {
				var cfLayer = MapView.Active.Map.GetLayersAsFlattenedList().First((l) => l.Name == "ContactsAndFaults") as FeatureLayer;
				cfLayer.SetRenderer(DataHelper.cfRenderer);
			} catch { }

		}

	}
});

 

0 Kudos
2 Solutions

Accepted Solutions
Wolf
by Esri Regular Contributor
Esri Regular Contributor

Hi Douglas,

 CIMSymbolReference.FromJson() can only de-serialize JSON that contains a CIMSymbolReference object.  The message "Wrong type name" refers the type that has been serialized into your JSON string: 

 

{
  "type": "CIMLineSymbol",
  ...

 

If you look at the serialized JSON for a CIMSymbolReference you should see a JSON string looking like this:

 

{
  "type": "CIMSymbolReference",
  "symbol": {
    "type": "CIMPolygonSymbol",
    "symbolLayers": [
      {
        "type": "CIMSolidStroke",
        "enable": true,
        "capStyle": "Round",
        "joinStyle": "Round",
        "lineStyle3D": "Strip",
        "miterLimit": 10,
        "width": 1,
        "color": {
          "type": "CIMRGBColor",
          "values": [
            0,
            0,
            0,
            100
          ]
        }
      },
      {
        "type": "CIMSolidFill",
        ....

 

View solution in original post

0 Kudos
Douglas_DMeredith
New Contributor II

Thanks for pointing this out. Wrapping the symbol JSON string with the CIMSymbolReference JSON string bits gets the job done.

It's not very elegant though. It would be nice if there were a FromJson() routine in CIMSymbol.

View solution in original post

0 Kudos
2 Replies
Wolf
by Esri Regular Contributor
Esri Regular Contributor

Hi Douglas,

 CIMSymbolReference.FromJson() can only de-serialize JSON that contains a CIMSymbolReference object.  The message "Wrong type name" refers the type that has been serialized into your JSON string: 

 

{
  "type": "CIMLineSymbol",
  ...

 

If you look at the serialized JSON for a CIMSymbolReference you should see a JSON string looking like this:

 

{
  "type": "CIMSymbolReference",
  "symbol": {
    "type": "CIMPolygonSymbol",
    "symbolLayers": [
      {
        "type": "CIMSolidStroke",
        "enable": true,
        "capStyle": "Round",
        "joinStyle": "Round",
        "lineStyle3D": "Strip",
        "miterLimit": 10,
        "width": 1,
        "color": {
          "type": "CIMRGBColor",
          "values": [
            0,
            0,
            0,
            100
          ]
        }
      },
      {
        "type": "CIMSolidFill",
        ....

 

View solution in original post

0 Kudos
Douglas_DMeredith
New Contributor II

Thanks for pointing this out. Wrapping the symbol JSON string with the CIMSymbolReference JSON string bits gets the job done.

It's not very elegant though. It would be nice if there were a FromJson() routine in CIMSymbol.

View solution in original post

0 Kudos