Strange behavior when using JsConfig.With

Hello,

Recently we have started using JsConfig.With in a method and we have a strange behavior. Our project is using .Net 4.6.1 and ServiceStack 5.9.0.

Our use case is as follow: we have a complex object that we want to serialize to store it as plain text. The object contain a byte[] property which we may not want to persist according to some business rules. For this, we have been trying to use JsConfig.With to create a new scope which uses ExcludeTypes to exclude the byte[] type.

We added a test to ensure that the byte[] property has not be serialized and everything appears to work at first glance. A few days later we had an issue where the new test randomly fails because the byte[] property was not removed as expected. This only happens when running every tests; running the failing test by itself in a loop does not reproduce the issue.

After investigating I was able to observer an issue with JsConfig.With which seems to be similar to my problem. You can find the code below to reproduce the issue, I tried it with ServiceStack 5.9 and the latest version (6.3) and the behavior is the same.

It appears that JsConfig is ignored. Can you see something in the code below I am not doing correctly?

Thanks

void Main()
{
	var o = new SomeObj
	{
		Name = "Freddie",
		Content = new byte[] { 42 }
	};

	// The weird thing is that if you swap the 2 lines below, both variable will not have the Content property
	
	var normalSerialization = NormalSerialization(o); // this variable should include the Content property
	var serializedWithoutByteArray = SerializeWithoutBytes(o); // this variable should NOT include the Content property

	Console.WriteLine("Normal Serialization: " + normalSerialization);
	Console.WriteLine("Serialization without byte[]: " + serializedWithoutByteArray);

	if (normalSerialization.IndexOf("content", StringComparison.OrdinalIgnoreCase) == -1)
	{
		Console.WriteLine("normalSerialization: the Content property is missing");
	}
	else
	{
		Console.WriteLine("normalSerialization: the Content property is present as expected");
	}

	if (serializedWithoutByteArray.IndexOf("content", StringComparison.OrdinalIgnoreCase) == -1)
	{
		Console.WriteLine("serializedWithoutByteArray: the Content property is missing as expected");
	}
	else
	{
		Console.WriteLine("serializedWithoutByteArray: the Content property should not be present");
	}

	if (serializedWithoutByteArray == normalSerialization)
	{
		throw new Exception("Serializing the object with a different JsConfig settings should generate a different value.");
	}

	string NormalSerialization<T>(T objToSerialize)
	{
		return objToSerialize.ToJson();
	}

	string SerializeWithoutBytes<T>(T objToSerialize)
	{
		using (var s = JsConfig.With(new Config
		{
			ExcludeTypes = new HashSet<Type>(new[] { typeof(byte[]) })
		}))
		{
			return objToSerialize.ToJson();
		}
	}
}

class SomeObj
{
	public string Name { get; set; }

	public byte[] Content { get; set; }
}

This was a property caching issue which should be resolved from this commit.

This fix is available from v6.3.1+ that’s now available on MyGet.

Thx for the repro!

Thanks for the quick response!

1 Like