Skip to content

Commit

Permalink
Refs #27 - works around an isssue with the CiviCRM API
Browse files Browse the repository at this point in the history
See: http://forum.civicrm.org/index.php/topic,35393.0.html
TODO: create an issue in the issue tracker.
  • Loading branch information
johanv committed Jan 12, 2015
1 parent f61f082 commit aeb94e9
Showing 1 changed file with 58 additions and 1 deletion.
59 changes: 58 additions & 1 deletion Chiro.CiviCrm.Behavior/NewtonsoftJsonClientFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ class NewtonsoftJsonClientFormatter : IClientMessageFormatter
{
readonly OperationDescription _operation;
readonly Uri _operationUri;

private static readonly Regex ValuesObjectInsteadOfArrayExpression = new Regex("\"values\":[{]");
private static readonly Regex KeyValueArrayItemExpression = new Regex("\"[0-9]+\":[{]");

public NewtonsoftJsonClientFormatter(OperationDescription operation, ServiceEndpoint endpoint)
{
this._operation = operation;
Expand All @@ -44,7 +48,30 @@ public object DeserializeReply(Message message, object[] parameters)
var serializer = new JsonSerializer();
bodyReader.ReadStartElement("Binary");
byte[] body = bodyReader.ReadContentAsBase64();
using (MemoryStream ms = new MemoryStream(body))

// If you chain an 'api.create' with multiple entities of the same type, the resulting Json cannot
// be parsed by the serializer. See this thread on the civicrm forums:
// http://forum.civicrm.org/index.php/topic,35393.0.html

string bodyString = Encoding.UTF8.GetString(body);

// Work around this issue:
while (KeyValueArrayItemExpression.IsMatch(bodyString))
{
int index = KeyValueArrayItemExpression.Matches(bodyString)[0].Index;
bodyString = KeyValueArrayItemExpression.Replace(bodyString, "{", 1);
bodyString = ReplaceCurlyBraces(bodyString, index, String.Empty, String.Empty);
body = Encoding.UTF8.GetBytes(bodyString);
}
while (ValuesObjectInsteadOfArrayExpression.IsMatch(bodyString))
{
int index = ValuesObjectInsteadOfArrayExpression.Matches(bodyString)[0].Index + 9;
bodyString = ValuesObjectInsteadOfArrayExpression.Replace(bodyString, "\"values\":{", 1);
bodyString = ReplaceCurlyBraces(bodyString, index, "[{", "}]");
body = Encoding.UTF8.GetBytes(bodyString);
}

using (var ms = new MemoryStream(body))
{
using (var sr = new StreamReader(ms))
{
Expand All @@ -55,6 +82,36 @@ public object DeserializeReply(Message message, object[] parameters)
}
}

private static string ReplaceCurlyBraces(string bodyString, int index, string newLeft, string newRight)
{
// Replace matching curly brace by square brace

Debug.Assert(bodyString[index] == '{');
int start = index + 1;

var builder = new StringBuilder(bodyString.Substring(0, index));
builder.Append(newLeft);

int level = 0;
while (level >= 0)
{
++index;
if (bodyString[index] == '{')
{
++level;
}
if (bodyString[index] == '}')
{
--level;
}
}

builder.Append(bodyString.Substring(start, index - start));
builder.Append(newRight);
builder.Append(bodyString.Substring(index + 1));
return builder.ToString();
}

public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
{
byte[] body;
Expand Down

0 comments on commit aeb94e9

Please sign in to comment.