From 080179c61f37a65c977dc8058692accf3ef311fd Mon Sep 17 00:00:00 2001 From: Shivaprasad-D-N1 Date: Tue, 21 Oct 2025 18:20:42 +0530 Subject: [PATCH 1/2] required files for JSON and XML serialization --- dotnet/Json-Xml-Serialization/Env.cs | 186 ++++++++++++ .../JSON_XML_Serialization.cs | 270 ++++++++++++++++++ .../JSON_XML_Serialization.csproj | 14 + .../JSON_XML_Serialization.sln | 25 ++ dotnet/Json-Xml-Serialization/Readme.md | 49 ++++ dotnet/Json-Xml-Serialization/env.json | 20 ++ 6 files changed, 564 insertions(+) create mode 100644 dotnet/Json-Xml-Serialization/Env.cs create mode 100644 dotnet/Json-Xml-Serialization/JSON_XML_Serialization.cs create mode 100644 dotnet/Json-Xml-Serialization/JSON_XML_Serialization.csproj create mode 100644 dotnet/Json-Xml-Serialization/JSON_XML_Serialization.sln create mode 100644 dotnet/Json-Xml-Serialization/Readme.md create mode 100644 dotnet/Json-Xml-Serialization/env.json diff --git a/dotnet/Json-Xml-Serialization/Env.cs b/dotnet/Json-Xml-Serialization/Env.cs new file mode 100644 index 00000000..f7c6be94 --- /dev/null +++ b/dotnet/Json-Xml-Serialization/Env.cs @@ -0,0 +1,186 @@ +/****************************************************************************************/ +/* */ +/* */ +/* Copyright 2025 IBM Corp. */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ +/* See the License for the specific language governing permissions and */ +/* limitations under the License. */ +/* */ +/* */ +/****************************************************************************************/ + + +using Newtonsoft.Json; + +namespace JSON_XML_Serialization +{ + class Env + { + public class MQEndPoints + { + public List? mq_endpoints; + } + + public class ConnVariables + { + public string host = null; + public string qmgr = null; + public int port = 0; + public string channel = null; + public string queue_name = null; + public string model_queue_name = null; + public string topic_name = null; + public string app_user = null; + public string app_password = null; + public string cipher_suite = null; + public string key_repository = null; + public bool is_managed = true; + public void dump() + { + Console.WriteLine("hostname {0} ", host); + Console.WriteLine("port {0} ", port); + Console.WriteLine("qmgr {0} ", qmgr); + Console.WriteLine("channel {0} ", channel); + Console.WriteLine("queue {0} ", queue_name); + Console.WriteLine("topic {0} ", topic_name); + Console.WriteLine("app_user {0} ", app_user); + Console.WriteLine($"is_managed {is_managed}"); + // Console.WriteLine("app_password {0} ", app_password); + Console.WriteLine("cipherSpec {0} ", cipher_suite); + Console.WriteLine("sslKeyRepository{0} ", key_repository); + } + } + + private MQEndPoints points = null; + private ConnVariables conn = null; + + internal ConnVariables Conn { get => conn; set => conn = value; } + + private bool AtLeast(int i) + { + if (i >= 0 && points != null && points.mq_endpoints != null && points.mq_endpoints.Count >= i) + { + return true; + } + return false; + } + + public int NumberOfConnections() + { + if (AtLeast(1)) + { + return points.mq_endpoints.Count; + } + return 0; + } + + private ConnVariables EndPoint(int i) + { + if (AtLeast(i)) + { + return points.mq_endpoints[i]; + } + return null; + } + + public IEnumerable GetEndpoints() + { + int count = NumberOfConnections(); + for (int i = 0; i < count; i++) + { + yield return points.mq_endpoints[i]; + } + } + + public string BuildConnectionString() + { + List connList = new List(); + + if (AtLeast(1)) + { + foreach (var c in points.mq_endpoints) + { + if (c.host != null && c.port != 0) + { + connList.Add(c.host + "(" + c.port.ToString() + ")"); + } + } + return string.Join(",", connList); + } + + return ""; + } + + public bool ReadJson(string getEnv) + { + bool isSet = false; + + using (StreamReader r = new StreamReader(getEnv)) + { + Console.WriteLine("File found"); + string json = r.ReadToEnd(); + + points = JsonConvert.DeserializeObject(json); + + if (points != null && points.mq_endpoints != null && points.mq_endpoints.Count > 0) + { + Conn = points.mq_endpoints[0]; + Conn.dump(); + isSet = true; + } + } + + return isSet; + } + + public bool EnvironmentIsSet() + { + bool isSet = false; + try + { + Console.WriteLine("Looking for file"); + + // Getting the path from env_variable : ENV_FILE + string getEnv = Environment.GetEnvironmentVariable("ENV_FILE"); + + if (getEnv == null || !ReadJson(getEnv)) + { + // Use the Default env.json in the project folder + getEnv = @"../../../env.json"; + if (ReadJson(getEnv)) + { + Console.WriteLine("Using Default env.json"); + isSet = true; + } + else + { + Console.WriteLine("MQ Settings not found, unable to determine connection variables"); + } + } + else + { + Console.WriteLine("Using externally Provided env.json"); + isSet = true; + } + + Console.WriteLine(""); + return isSet; + } + catch (Exception e) + { + Console.WriteLine("Exception caught: {0}", e); + Console.WriteLine(e.GetBaseException()); + return isSet; + } + } + } +} \ No newline at end of file diff --git a/dotnet/Json-Xml-Serialization/JSON_XML_Serialization.cs b/dotnet/Json-Xml-Serialization/JSON_XML_Serialization.cs new file mode 100644 index 00000000..165c804a --- /dev/null +++ b/dotnet/Json-Xml-Serialization/JSON_XML_Serialization.cs @@ -0,0 +1,270 @@ +/****************************************************************************************/ +/* */ +/* */ +/* Copyright 2025 IBM Corp. */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ +/* See the License for the specific language governing permissions and */ +/* limitations under the License. */ +/* */ +/* */ +/****************************************************************************************/ +/* */ +/* FILE NAME: JSON_XML_Serialization.cs */ +/* */ +/* DESCRIPTION: A Shared Class with Serialize and Deserialize methods for */ +/* Json and XML Objects */ +/* */ +/****************************************************************************************/ + + +using IBM.WMQ; +using System.Collections; +using System.Xml.Serialization; +using System.Text.Json; + +namespace JSON_XML_Serialization +{ + public class Person + { + public string Name { get; set; } + public int Age { get; set; } + } + + public class JSON_XML_Serialization + { + // Env object to get the Endpoint Values from the JSON + private static Env env = new Env(); + private static MQQueueManager queueManager; + + static void Main(String[] args) + { + try + { + string token; + if (args.Length < 1) + { + Console.WriteLine("Available Operations:"); + Console.WriteLine(" PutJSON - Serialize an object to JSON and send it to the IBM MQ queue."); + Console.WriteLine(" GetJSON - Receive a message from the IBM MQ queue and deserialize it from JSON to an object."); + Console.WriteLine(" PutXML - Serialize an object to XML and send it to the IBM MQ queue."); + Console.WriteLine(" GetXML - Receive a message from the IBM MQ queue and deserialize it from XML to an object."); + + Console.WriteLine("\nNote: Choices are case-insensitive."); + } + + else + { + if (env.EnvironmentIsSet()) + { + var connectionProperties = new Hashtable { + { MQC.USER_ID_PROPERTY, env.Conn.app_user}, + { MQC.PASSWORD_PROPERTY, env.Conn.app_password }, + { MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED}, + { MQC.HOST_NAME_PROPERTY, env.Conn.host}, + { MQC.PORT_PROPERTY, env.Conn.port }, + { MQC.CHANNEL_PROPERTY, env.Conn.channel } + }; + + queueManager = new MQQueueManager("", connectionProperties); + } + + token = args[0].ToLower(); + switch (token) + { + case "putjson": + JSON_XML_Serialization.PutJSON(); + break; + case "getjson": + JSON_XML_Serialization.GetJSON(); + break; + case "putxml": + JSON_XML_Serialization.PutXML(); + break; + case "getxml": + JSON_XML_Serialization.GetXML(); + break; + default: + Console.WriteLine("Choose which operation to perform; PutJSON, GetJSON, PutXML, GetXML"); + break; + } + } + } + catch (MQException E) + { + Console.WriteLine("Exception Caught : " + E); + } + } + + public static void PutJSON() + { + Person person = new Person + { + Name = "Alice", + Age = 28 + }; + + string jsonString = JsonSerializer.Serialize(person); + + string queueName = env.Conn.queue_name; + + Console.Write("Accessing queue " + queueName + ".. "); + var queue = queueManager.AccessQueue(queueName, MQC.MQOO_OUTPUT + MQC.MQOO_FAIL_IF_QUIESCING); + Console.WriteLine("done"); + + var message = new MQMessage(); + message.WriteUTF(jsonString); + + for (int i = 1; i <= 5; i++) + { + Console.Write("Message " + i + " - "); + queue.Put(message); + Console.WriteLine("put successfully onto the queue"); + } + + queue.Close(); + } + + public static void GetJSON() + { + string queueName = env.Conn.queue_name; + + Console.Write("Accessing queue " + queueName + ".. "); + var queue = queueManager.AccessQueue(queueName, MQC.MQOO_OUTPUT + MQC.MQOO_FAIL_IF_QUIESCING + MQC.MQOO_INPUT_AS_Q_DEF); + Console.WriteLine("done"); + + var message = new MQMessage(); + + while (true) + { + try + { + queue.Get(message); + if (message != null) + { + //string JsonString = message.ReadString(message.MessageLength / 2); + string JsonString = message.ReadUTF(); + Person deserialized = JsonSerializer.Deserialize(JsonString); + + Console.WriteLine($"Name: {deserialized.Name}, Age: {deserialized.Age}"); + } + else + { + Console.WriteLine("No More Messages"); + break; + } + } + + catch (MQException MQE) + { + if (MQE.ReasonCode == 2033) + { + Console.WriteLine("No More Messages"); + break; + } + + Console.WriteLine("Excpetion Caught : " + MQE); + break; + } + + } + + queue.Close(); + + } + + public static void PutXML() + { + var person = new Person { Name = "Alice", Age = 30 }; + XmlSerializer serializer = new XmlSerializer(typeof(Person)); + + string xmlString; + using (StringWriter writer = new StringWriter()) + { + serializer.Serialize(writer, person); + xmlString = writer.ToString(); + } + Console.WriteLine("Serialized XML Data : " + xmlString); + + string queueName = env.Conn.queue_name; + + Console.Write("Accessing queue " + queueName + ".. "); + var queue = queueManager.AccessQueue(queueName, MQC.MQOO_OUTPUT + MQC.MQOO_FAIL_IF_QUIESCING); + Console.WriteLine("done"); + + var message = new MQMessage(); + message.WriteString(xmlString); + + for (int i = 1; i <= 5; i++) + { + Console.Write("Message " + i + " - "); + queue.Put(message); + Console.WriteLine("put successfully onto the queue"); + } + + queue.Close(); + } + + public static void GetXML() + { + string queueName = env.Conn.queue_name; + + Console.Write("Accessing queue " + queueName + ".. "); + var queue = queueManager.AccessQueue(queueName, MQC.MQOO_OUTPUT + MQC.MQOO_FAIL_IF_QUIESCING + MQC.MQOO_INPUT_AS_Q_DEF); + Console.WriteLine("done"); + + var message = new MQMessage(); + XmlSerializer serializer = new XmlSerializer(typeof(Person)); + Person deserialized; + string xmlString; + + while (true) + { + try + { + queue.Get(message); + if (message != null) + { + xmlString = message.ReadString(message.MessageLength / 2); + Console.WriteLine("XML String : " + xmlString); + using (StringReader reader = new StringReader(xmlString)) + { + deserialized = (Person)serializer.Deserialize(reader); + } + + Console.WriteLine("\nDeserialized object:"); + Console.WriteLine($"Name = {deserialized.Name}, Age = {deserialized.Age}"); + } + else + { + Console.WriteLine("No More Messages"); + break; + } + } + + catch(MQException MQE) + { + if (MQE.ReasonCode == 2033) + { + Console.WriteLine("No More Messages"); + break; + } + + Console.WriteLine("Excpetion Caught : " + MQE); + break; + } + + } + + queue.Close(); + } + } +} \ No newline at end of file diff --git a/dotnet/Json-Xml-Serialization/JSON_XML_Serialization.csproj b/dotnet/Json-Xml-Serialization/JSON_XML_Serialization.csproj new file mode 100644 index 00000000..6e95050f --- /dev/null +++ b/dotnet/Json-Xml-Serialization/JSON_XML_Serialization.csproj @@ -0,0 +1,14 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + diff --git a/dotnet/Json-Xml-Serialization/JSON_XML_Serialization.sln b/dotnet/Json-Xml-Serialization/JSON_XML_Serialization.sln new file mode 100644 index 00000000..09e4b068 --- /dev/null +++ b/dotnet/Json-Xml-Serialization/JSON_XML_Serialization.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 25.0.1706.14 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JSON_XML_Serialization", "JSON_XML_Serialization\JSON_XML_Serialization.csproj", "{5DCC5071-C517-432A-88BB-BA3918A8D8F9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5DCC5071-C517-432A-88BB-BA3918A8D8F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5DCC5071-C517-432A-88BB-BA3918A8D8F9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5DCC5071-C517-432A-88BB-BA3918A8D8F9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5DCC5071-C517-432A-88BB-BA3918A8D8F9}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {AE4B4565-069B-411D-A436-7DC73845A113} + EndGlobalSection +EndGlobal diff --git a/dotnet/Json-Xml-Serialization/Readme.md b/dotnet/Json-Xml-Serialization/Readme.md new file mode 100644 index 00000000..c670b054 --- /dev/null +++ b/dotnet/Json-Xml-Serialization/Readme.md @@ -0,0 +1,49 @@ +# IBM MQ .NET sample to Imitate the Serialization and Deserialization of Objects using JSON and XML Serializers + +The .NET sample are based on the existing samples shipped with IBM MQ Server and Client Packages. The sample here have been tested with .NET 8.0 and Visual Studio 2023 v 25.0.1706.3. Also it has been tested with Visual Studio for Mac 2023 v 25.0.1706.3. + +We have included '.sln', '.csproj', 'packages.config'. These were created with the Visual Studio Community 2023. We've also added the copy of the 'env.json' file from the top level directory to the '/dotnet' project directory, the files will be copied to '/bin/Debug/net8.0' and adjust the parameters to use your own queue manager. +The User can also provide their external env.json by setting the environment variable ENV_FILE. + +## References from Visual Studio + +- **[IBM MQ .NET Client package](https://www.nuget.org/packages/IBMMQDotnetClient) : Used to make MQ API calls.** +- **[Newtonsoft JSON package](https://www.nuget.org/packages/Newtonsoft.Json/) : Used for Reading the Endpoints from the provided `env.json` file.** + +Reference it through Solution Explorer NuGet Package installer + +## JSON-Serialization and JSON-Deserialization + +We use the JSON serializer and deserializer available in the `System.Text.Json` package. +Objects are serialized before performing a "Put" operation on the queue, and deserialized after performing a "Get" operation. + +Both operations have been tested through the provided project. + +To run the project, execute the `.exe` file from the command line. +Navigate to the appropriate directory based on your build configuration: + +- `bin\Debug\` (for Debug builds) +- `bin\Release\` (for Release builds) + +For Example : + +- `JSON_XML_Serialization.exe putjson` - Puts a JSON-serialized object onto an IBM MQ queue. +- `JSON_XML_Serialization.exe getjson` - Retrieves and deserializes a JSON-serialized message from an IBM MQ queue. + +## XML-Serialization and XML-Deserialization + +We use the XML serializer and deserializer available in the `System.Xml.Serialization` package. +Objects are serialized before performing a "Put" operation on the queue, and deserialized after performing a "Get" operation. + +Both operations have been tested through the provided project. + +To run the project, execute the `.exe` file from the command line. +Navigate to the appropriate directory based on your build configuration: + +- `bin\Debug\` (for Debug builds) +- `bin\Release\` (for Release builds) + +For Example : + +- `JSON_XML_Serialization.exe putxml` - Puts a XML-serialized object onto an IBM MQ queue. +- `JSON_XML_Serialization.exe getxml` - Retrieves and deserializes a XML-serialized message from an IBM MQ queue. diff --git a/dotnet/Json-Xml-Serialization/env.json b/dotnet/Json-Xml-Serialization/env.json new file mode 100644 index 00000000..aa9b3189 --- /dev/null +++ b/dotnet/Json-Xml-Serialization/env.json @@ -0,0 +1,20 @@ +{ + "MQ_ENDPOINTS": [ + { + "HOST": "127.0.0.1", + "PORT": "5672", + "CHANNEL": "DEV.APP.SVRCONN", + "QMGR": "*QM1TLS", + "APP_USER": "app", + "APP_PASSWORD": "passw0rd", + "QUEUE_NAME": "DEV.QUEUE.1", + "BACKOUT_QUEUE": "DEV.QUEUE.2", + "MODEL_QUEUE_NAME": "DEV.APP.MODEL.QUEUE", + "DYNAMIC_QUEUE_PREFIX": "APP.REPLIES.*", + "TOPIC_NAME": "dev/", + "CIPHER": "TLS_RSA_WITH_AES_128_CBC_SHA256", + "CIPHER_SUITE": "TLS_RSA_WITH_AES_128_CBC_SHA256", + "KEY_REPOSITORY": "../keys/clientkey" + } + ] +} From 3dffc13c96b7f441adb3adf196ae777320a83e48 Mon Sep 17 00:00:00 2001 From: Shivaprasad-D-N1 Date: Thu, 23 Oct 2025 11:29:50 +0530 Subject: [PATCH 2/2] updated the Readme --- dotnet/Json-Xml-Serialization/Readme.md | 45 ++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/dotnet/Json-Xml-Serialization/Readme.md b/dotnet/Json-Xml-Serialization/Readme.md index c670b054..1690137f 100644 --- a/dotnet/Json-Xml-Serialization/Readme.md +++ b/dotnet/Json-Xml-Serialization/Readme.md @@ -1,6 +1,49 @@ # IBM MQ .NET sample to Imitate the Serialization and Deserialization of Objects using JSON and XML Serializers -The .NET sample are based on the existing samples shipped with IBM MQ Server and Client Packages. The sample here have been tested with .NET 8.0 and Visual Studio 2023 v 25.0.1706.3. Also it has been tested with Visual Studio for Mac 2023 v 25.0.1706.3. +## Overview + +Serialization is the process of converting an object into a format that can be stored (string, file, database) or transmitted (network). Deserialization is the reverse: converting that format back into an object. + +`ReadObject` and `WriteObject` are methods provided in the IBM MQ .NET libraries (both in the base IBM.WMQ classes and the higher-level IBM.XMS API) that allow applications to serialize and deserialize .NET objects into MQ message bodies. These methods simplify the process of sending complex objects over MQ by automatically converting them to and from a binary format using the .NET `BinaryFormatter`. However, this approach relies on binary serialization, which has been removed by Microsoft due to multiple security risks, including the potential for remote code execution when deserializing untrusted data. + +To align with Microsoft’s direction and ensure the long-term security and compatibility of IBM MQ .NET applications, the `ReadObject` and `WriteObject` methods are being removed starting with IBM MQ .NET 9.4.4 Continuous Delivery(CD) release. With the complete removal of `BinaryFormatter` in .NET 9, continuing to support these methods would pose security and platform compatibility issues. Applications should migrate to using explicit serialization approaches such as JSON or XML, using `TextMessage` or `BytesMessage`, which provide safer, more interoperable and future-proof alternatives for exchanging structured data across systems. + +**IBM MQ Documentation : [Deprecated, stabilized and removed features in IBM MQ 9.4.4](https://www.ibm.com/docs/en/ibm-mq/9.4.x?topic=944-deprecated-stabilized-removed-features-in-mq)** + +There are two main types of serializers that can be used as replacements for BinaryFormatter. + +1. JSON Serialization using "System.Text.Json" +2. XML Serialization using "XmlSerializer" + +### JSON Serialization (System.Text.Json) + +- What it is : Converts objects into JSON (JavaScript Object Notation). +- Format : Human-readable, lightweight, widely used in APIs and web applications. +- Serialization : Converts an object into a JSON string, which can be saved into a .json file. +- Deserialization : Reads the JSON string and reconstructs the original object. +- Advantages : + 1. Fast and efficient + 2. Built into modern .NET versions (no extra packages required) + 3. Widely supported across platforms + +- Best for : Web APIs, config files, data exchange with JavaScript or REST services. + +### XML Serialization (System.Xml.Serialization) + +- What it is : Converts objects into XML (Extensible Markup Language). +- Format : More verbose, but standardized and supported by many systems. +- Serialization : Converts an object into XML format, which can be saved into a .xml file. +- Deserialization : Reads the XML content and reconstructs the object. +- Advantages : + 1. Human-readable with strong schema support + 2. Good for interoperability with legacy systems + 3. Can be validated against XSD schemas + +- Best for : Configurations, enterprise systems, or when working with systems that require XML. + +### Sample Overview + +The .NET sample is based on the existing samples shipped with IBM MQ Server and Client Packages. The sample here have been tested with .NET 8.0 and Visual Studio 2023 v 25.0.1706.3. Also it has been tested with Visual Studio for Mac 2023 v 25.0.1706.3. We have included '.sln', '.csproj', 'packages.config'. These were created with the Visual Studio Community 2023. We've also added the copy of the 'env.json' file from the top level directory to the '/dotnet' project directory, the files will be copied to '/bin/Debug/net8.0' and adjust the parameters to use your own queue manager. The User can also provide their external env.json by setting the environment variable ENV_FILE.