We have a very large List<object> that we are turning into a json string and then sending to a stored procedure. To keep things simple for this post, let's say the object looks like this:
public class Customer
{
public string Name { get; set; }
}
And one of the customers is "Bob's Repair Shop". When the list with this value in it gets serialized, it will contain this:
{
"Name": "Bob's Repair Shop"
}
That's ok, right up until we want to send this json into a stored procedure. When it gets there, that single quote throws an error (which I understand).
Originally we handled this by doing a .replace("'", "~") on the json string in the C# code, and then doing the reverse in the stored proc. That worked for a while. But what we are running into now is that the object we have a List<> of is much more complex that this little example, and we are also dealing with several hundred thousand records in the list. When the json string is this large, the .replace("'", "~") throws an Out of Range exception. And let's be honest, this .replace("'", "~") approach is a hack anyway.
What I'm hoping to find is a way to serialize our List<object> in such a way that the single quotes are escaped during the serialization process. Is this possible? And if so, how?
EDIT:
I really should have said this originally. Sorry I missed it. Here's how the stored proc is receiving the json string:
ALTER PROCEDURE [dbo].[name_of_proc]
@jsonString NVARCHAR(MAX)
AS
And then we convert the @jsonString to a table variable with OPENJSON
EDIT 2:
how the sp is called:
public void UpdateBulk(List<object> myObject)
{
string json = Newtonsoft.Json.JsonConvert.SerializeObject(myObject);
json.replace("'", "~");
var dParam = new DynamicParameters();
dParam.Add("@jsonString", json);
QuerySP<myObject>("name_of_proc", dParam);
}
protected IEnumerable<T> QuerySP<T>(string storedProcedure, object param = null)
{
using (var db = this.Context)
{
var output = db.Query<T>(storedProcedure, param: param, commandType: CommandType.StoredProcedure,commandTimeout: 32767);
return output;
}
}
EDIT 3: The thread pointed to as a possible duplicate asks how to change this:
{"key" : "value"}
to this:
{'key' : 'value'}
That's not what I'm asking. I'm asking how to change this:
{
"Name": "Bob's Repair Shop"
}
To this:
{
"Name": "Bob\'s Repair Shop"
}
You could add a custom JSON converter to perform the replacement on individual string instances while the serialization is taking place. This is still using string.Replace, but all the string instances should be small at this point.
public class EscapeQuotes : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(string);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var escapedValue = ((string)value).Replace("'", "\\'");
writer.WriteValue(escapedValue);
}
}
Usage:
Customer myObject = new Customer() { Name = "Bob's repair shop" };
var output = JsonConvert.SerializeObject(myObject, new EscapeQuotes());
Output:
{"Name":"Bob\\'s repair shop"}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With