Skip to content

Commit

Permalink
Merge pull request #881 from gbirchmeier/i877-toJSON
Browse files Browse the repository at this point in the history
throw ex if Message.ToJSON(null,true) called
  • Loading branch information
gbirchmeier authored Sep 12, 2024
2 parents 611c841 + f74510c commit 93bf6ee
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 18 deletions.
2 changes: 1 addition & 1 deletion Examples/FixToJson/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ static void FixToJson(
{
line = line.Trim();
msg.FromString(line, false, sessionDataDictionary, appDataDictionary, msgFactory);
Console.WriteLine(comma + msg.ToJSON(humanReadableValues: humanReadableValues));
Console.WriteLine(comma + msg.ToJSON(convertEnumsToDescriptions: humanReadableValues));
comma = ",";
}
}
Expand Down
23 changes: 14 additions & 9 deletions QuickFIXn/Message/Message.cs
Original file line number Diff line number Diff line change
Expand Up @@ -946,17 +946,22 @@ public string ToXML(DD? dataDictionary = null)
/// Per the FIX JSON Encoding spec, tags are converted to human-readable form, but values are not.
/// </summary>
/// <param name="dataDictionary">Needed if you want tag names emitted or humanReadableValues to work</param>
/// <param name="humanReadableValues">
/// True will cause enums to be converted to human strings.
/// Will not (and cannot!) work if dataDictionary is null.
/// <param name="convertEnumsToDescriptions">
/// True will cause enums to be converted to their description strings, but only if dataDictionary is provided.
/// If true and dataDictionary is null, then throws an ArgumentNullException.
/// </param>
/// <returns>a JSON string</returns>
public string ToJSON(DD? dataDictionary = null, bool humanReadableValues = false)
{
StringBuilder sb = new StringBuilder().Append("{").Append("\"Header\":{");
FieldMapToJSON(sb, dataDictionary, Header, humanReadableValues).Append("},\"Body\":{");
FieldMapToJSON(sb, dataDictionary, this, humanReadableValues).Append("},\"Trailer\":{");
FieldMapToJSON(sb, dataDictionary, Trailer, humanReadableValues).Append("}}");
public string ToJSON(DD? dataDictionary = null, bool convertEnumsToDescriptions = false) {
if (convertEnumsToDescriptions && dataDictionary is null) {
throw new ArgumentNullException(
nameof(dataDictionary),
$"Must be non-null if '{nameof(convertEnumsToDescriptions)}' is true.");
}

StringBuilder sb = new StringBuilder().Append('{').Append("\"Header\":{");
FieldMapToJSON(sb, dataDictionary, Header, convertEnumsToDescriptions).Append("},\"Body\":{");
FieldMapToJSON(sb, dataDictionary, this, convertEnumsToDescriptions).Append("},\"Trailer\":{");
FieldMapToJSON(sb, dataDictionary, Trailer, convertEnumsToDescriptions).Append("}}");
return sb.ToString();
}
}
Expand Down
6 changes: 4 additions & 2 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@ What's New
### (next release)

**Breaking changes**
* #878 - corrections to tag 45 "Side" in various DDs (gbirchmeier)
* #878 - corrections to tag 45 "Side" in various DDs (gbirchmeier) - most people won't notice, easy fix if they do
* fix typo in FIX50 and FIX50SP1: `CROSS_SHORT_EXXMPT` fixed to `CROSS_SHORT_EXEMPT`
* correction in FIX41 and FIX42: `D` to `UNDISCLOSED`

**Non-breaking changes**
* #877 - throw an exception if Message.ToJSON(dd=null,convertEnumsToDescriptions=true) is called (gbirchmeier)

### v1.12.0

**Breaking changes**
Expand Down Expand Up @@ -75,7 +78,6 @@ What's New
* Some classes were internalized, but I can't imagine people are using them in their app code.
* See details/explanation at https://github.com/connamara/quickfixn/pull/830


**Non-breaking changes**
* #400 - added DDTool, a C#-based codegen, and deleted Ruby-based generator (gbirchmeier)
* #811 - convert AT platform to be NUnit-based, get rid of Ruby runner (Rob-Hague)
Expand Down
19 changes: 13 additions & 6 deletions UnitTests/MessageToXmlTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,21 @@ public void ToJSONWithGroupsTest()
QuickFix.FIX44.ExecutionReport msg = new QuickFix.FIX44.ExecutionReport();
msg.FromString(msgStr, true, dd, dd, null); // <-- null factory!

string expected = "{\"Header\":{\"BeginString\":\"FIX.4.4\",\"BodyLength\":\"638\",\"MsgSeqNum\":\"360\",\"MsgType\":\"8\",\"SenderCompID\":\"BLPTSOX\",\"SendingTime\":\"20130321-15:21:23\",\"TargetCompID\":\"THINKTSOX\",\"TargetSubID\":\"6804469\",\"DeliverToCompID\":\"ZERO\"},\"Body\":{\"AvgPx\":\"122.255\",\"ClOrdID\":\"61101189\",\"CumQty\":\"1990000\",\"Currency\":\"GBP\",\"ExecID\":\"VCON:20130321:50018:5:12\",\"SecurityIDSource\":\"4\",\"LastPx\":\"122.255\",\"LastQty\":\"1990000\",\"OrderID\":\"116\",\"OrderQty\":\"1990000\",\"OrdStatus\":\"2\",\"SecurityID\":\"GB0032452392\",\"Side\":\"1\",\"Symbol\":\"[N/A]\",\"TransactTime\":\"20130321-15:21:23\",\"SettlDate\":\"20130322\",\"TradeDate\":\"20130321\",\"Issuer\":\"UK TSY 4 1/4% 2036\",\"NetMoney\":\"2436321.85\",\"ExecType\":\"F\",\"LeavesQty\":\"0\",\"NumDaysInterest\":\"15\",\"AccruedInterestAmt\":\"3447.35\",\"OrderQty2\":\"0\",\"SecondaryOrderID\":\"3739:20130321:50018:5\",\"CouponRate\":\"0.0425\",\"Factor\":\"1\",\"Yield\":\"0.0291371041\",\"Concession\":\"0\",\"GrossTradeAmt\":\"2432874.5\",\"PriceType\":\"1\",\"CountryOfIssue\":\"GB\",\"MaturityDate\":\"20360307\",\"NoPartyIDs\":[{\"PartyIDSource\":\"D\",\"PartyID\":\"VCON\",\"PartyRole\":\"1\",\"NoPartySubIDs\":[{\"PartySubID\":\"14\",\"PartySubIDType\":\"4\"}]},{\"PartyIDSource\":\"D\",\"PartyID\":\"TFOLIO:6804469\",\"PartyRole\":\"12\"},{\"PartyIDSource\":\"D\",\"PartyID\":\"TFOLIO\",\"PartyRole\":\"11\"},{\"PartyIDSource\":\"D\",\"PartyID\":\"THINKFOLIO LTD\",\"PartyRole\":\"13\"},{\"PartyIDSource\":\"D\",\"PartyID\":\"SXT\",\"PartyRole\":\"16\"},{\"PartyIDSource\":\"D\",\"PartyID\":\"TFOLIO:6804469\",\"PartyRole\":\"36\"}]},\"Trailer\":{}}";
Assert.AreEqual(expected, msg.ToJSON(dataDictionary: dd, humanReadableValues: false));
// CASE 1: params (dd, false) => tags converted to names, enums are not converted
const string expected = "{\"Header\":{\"BeginString\":\"FIX.4.4\",\"BodyLength\":\"638\",\"MsgSeqNum\":\"360\",\"MsgType\":\"8\",\"SenderCompID\":\"BLPTSOX\",\"SendingTime\":\"20130321-15:21:23\",\"TargetCompID\":\"THINKTSOX\",\"TargetSubID\":\"6804469\",\"DeliverToCompID\":\"ZERO\"},\"Body\":{\"AvgPx\":\"122.255\",\"ClOrdID\":\"61101189\",\"CumQty\":\"1990000\",\"Currency\":\"GBP\",\"ExecID\":\"VCON:20130321:50018:5:12\",\"SecurityIDSource\":\"4\",\"LastPx\":\"122.255\",\"LastQty\":\"1990000\",\"OrderID\":\"116\",\"OrderQty\":\"1990000\",\"OrdStatus\":\"2\",\"SecurityID\":\"GB0032452392\",\"Side\":\"1\",\"Symbol\":\"[N/A]\",\"TransactTime\":\"20130321-15:21:23\",\"SettlDate\":\"20130322\",\"TradeDate\":\"20130321\",\"Issuer\":\"UK TSY 4 1/4% 2036\",\"NetMoney\":\"2436321.85\",\"ExecType\":\"F\",\"LeavesQty\":\"0\",\"NumDaysInterest\":\"15\",\"AccruedInterestAmt\":\"3447.35\",\"OrderQty2\":\"0\",\"SecondaryOrderID\":\"3739:20130321:50018:5\",\"CouponRate\":\"0.0425\",\"Factor\":\"1\",\"Yield\":\"0.0291371041\",\"Concession\":\"0\",\"GrossTradeAmt\":\"2432874.5\",\"PriceType\":\"1\",\"CountryOfIssue\":\"GB\",\"MaturityDate\":\"20360307\",\"NoPartyIDs\":[{\"PartyIDSource\":\"D\",\"PartyID\":\"VCON\",\"PartyRole\":\"1\",\"NoPartySubIDs\":[{\"PartySubID\":\"14\",\"PartySubIDType\":\"4\"}]},{\"PartyIDSource\":\"D\",\"PartyID\":\"TFOLIO:6804469\",\"PartyRole\":\"12\"},{\"PartyIDSource\":\"D\",\"PartyID\":\"TFOLIO\",\"PartyRole\":\"11\"},{\"PartyIDSource\":\"D\",\"PartyID\":\"THINKFOLIO LTD\",\"PartyRole\":\"13\"},{\"PartyIDSource\":\"D\",\"PartyID\":\"SXT\",\"PartyRole\":\"16\"},{\"PartyIDSource\":\"D\",\"PartyID\":\"TFOLIO:6804469\",\"PartyRole\":\"36\"}]},\"Trailer\":{}}";
Assert.AreEqual(expected, msg.ToJSON(dataDictionary: dd, convertEnumsToDescriptions: false));

// emit enums as human-readable strings
StringAssert.Contains("\"MsgType\":\"EXECUTION_REPORT\"", msg.ToJSON(dataDictionary: dd, humanReadableValues: true));
// CASE 2: params (dd, true) => tags converted to names, enums are converted to names
StringAssert.Contains("\"MsgType\":\"EXECUTION_REPORT\"", msg.ToJSON(dataDictionary: dd, convertEnumsToDescriptions: true));

// Without a DD: tags aren't translated, and you don't get enums either
StringAssert.Contains("\"35\":\"8\"", msg.ToJSON(dataDictionary: null, humanReadableValues: true));
// CASE 3: params (null, false) => tags are numbers, enums are not converted
StringAssert.Contains("\"35\":\"8\"", msg.ToJSON(dataDictionary: null));

// EXCEPTION CASE: params (null, true) => Exception
var ex = Assert.Throws<ArgumentNullException>(delegate { msg.ToJSON(null, true); });
StringAssert.Contains(
"Must be non-null if 'convertEnumsToDescriptions' is true. (Parameter 'dataDictionary')",
ex.Message);
}
}
}

0 comments on commit 93bf6ee

Please sign in to comment.