diff --git a/Examples/FixToJson/Program.cs b/Examples/FixToJson/Program.cs
index 2142ba359..d02cedf3e 100644
--- a/Examples/FixToJson/Program.cs
+++ b/Examples/FixToJson/Program.cs
@@ -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 = ",";
}
}
diff --git a/QuickFIXn/Message/Message.cs b/QuickFIXn/Message/Message.cs
index 333f286b4..5d22087b0 100644
--- a/QuickFIXn/Message/Message.cs
+++ b/QuickFIXn/Message/Message.cs
@@ -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.
///
/// Needed if you want tag names emitted or humanReadableValues to work
- ///
- /// True will cause enums to be converted to human strings.
- /// Will not (and cannot!) work if dataDictionary is null.
+ ///
+ /// 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.
///
/// a JSON string
- 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();
}
}
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 43dc9201e..9f09140c0 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -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**
@@ -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)
diff --git a/UnitTests/MessageToXmlTests.cs b/UnitTests/MessageToXmlTests.cs
index 7596b5b4d..8d22a3b89 100644
--- a/UnitTests/MessageToXmlTests.cs
+++ b/UnitTests/MessageToXmlTests.cs
@@ -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(delegate { msg.ToJSON(null, true); });
+ StringAssert.Contains(
+ "Must be non-null if 'convertEnumsToDescriptions' is true. (Parameter 'dataDictionary')",
+ ex.Message);
}
}
}