1
LXO to json serialisation?
Question asked by Jean-Pierre Alvarez - 3/3/2023 at 2:47 PM
Answered
Hello,

I'm trying to convert liquid objects into json. For this I simply created a new instance of my object and used the serializer, let's call the class in question "Toto". "Toto" is generated by LXO and inherits from "LxBase" :

        [Fact]
        public void LiquidToJsonTest()
        {
            Toto toto = new Toto();

            var serializer = new LjSerializer<Toto>();
            string json;

            using (MemoryStream stream = new MemoryStream())
            {
                serializer.Serialize(stream, toto);
                stream.Position = 0;
                json = Encoding.UTF8.GetString(stream.ToArray());
            }

            using (MemoryStream memoryStream = GenerateStreamFromString(json))
            {
                Toto toto = serializer.Deserialize(memoryStream);
            }
        }

By doing this I get this error:
"LiquidTechnologies.XmlObjects.LxException: 'No class could be found to deserialize the root element Toto'"

I also tried deserializing an xml file with "LxSerializer" and then serializing it to json, and it worked. The difference between a json created from a new instance of my object and the json obtained from the xml is that in the second one I had the list of "xmlns:AA=...." declared, they were present in the xml file and added in "Toto.UnprocessedAttributes" when the file was read, while for a "new Toto()" the UnprocessedAttributes were empty, so there were nothing in the json either and it was impossible to deserialize it.

I tried to use settings for serialization with JsonRoundTrip.Full or JsonRoundTrip.Basic but that changed nothing.


So, my question is, how do I serialize an LXO object to json that contains all the necessary "xmlns..." without me having to add them by hand?

Thank you,
Jean-Pierre

6 Replies

Reply to Thread
0
Liquid Support Replied
Employee Post
Hi,

I'm not seeing an issue when I use the Bookstore sample...
using LiquidTechnologies.XmlObjects;
using LiquidXmlObjects.BookStore.Bs;
using System;
using System.IO;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            string sampleXml = @"<bs:bookstore xmlns:bs='http://www.liquid-technologies.com/sample/bookstore'; >
                        <bs:book price='23.99' publicationdate='2002-06-01' ISBN='0596002521'>
                            <bs:title>XML Schema</bs:title>
                            <bs:author>
                                <bs:first-name>Eric</bs:first-name>
                                <bs:last-name>van der Vlist</bs:last-name>
                            </bs:author>
                            <bs:genre>Reference</bs:genre>
                        </bs:book>
                    </bs:bookstore>";

            LxSerializer<BookstoreElm> serializer = new LxSerializer<BookstoreElm>();
            BookstoreElm bookstore;

            using (StringReader reader = new StringReader(sampleXml))
            {
                bookstore = serializer.Deserialize(reader);
            }

            BookTypeCt newBook = new BookTypeCt();
            newBook.Price = 7.99;
            newBook.Publicationdate = LxDateTime.CreateDate(2001, 12, 07);
            newBook.ISBN = "9780130655677";
            newBook.Title = "Definitive XML Schema";
            newBook.Author.First_Name = "Priscilla";
            newBook.Author.Last_Name = "Walmsley";
            newBook.Genre = "Reference";
            bookstore.Books.Add(newBook);

            // Display details about the books
            foreach (var book in bookstore.Books)
                Console.WriteLine($"Book[{book.Genre}] : '{book.Title}' ('${book.Price}') by '{book.Author.First_Name} {book.Author.Last_Name}' published on '{book.Publicationdate}'");


            using (StringWriter writer = new StringWriter())
            {
                serializer.Serialize(writer, bookstore);
                Console.WriteLine(writer.ToString());
            }

            string sampleJson;
            LjSerializer<BookstoreElm> jSerializer = new LjSerializer<BookstoreElm>();
            using (StringWriter jWriter = new StringWriter())
            {
                jSerializer.Serialize(jWriter, bookstore);
                sampleJson = jWriter.ToString();
                Console.WriteLine(sampleJson);
            }

            using (StringReader jReader = new StringReader(sampleJson))
            {
                bookstore = jSerializer.Deserialize(jReader);
            }

            using (StringWriter writer = new StringWriter())
            {
                serializer.Serialize(writer, bookstore);
                Console.WriteLine(writer.ToString());
            }

            // Display details about the books
            foreach (var book in bookstore.Books)
                Console.WriteLine($"Book[{book.Genre}] : '{book.Title}' ('${book.Price}') by '{book.Author.First_Name} {book.Author.Last_Name}' published on '{book.Publicationdate}'");
        }
    }
}
This code uses the XML Serializer to read XML data into the object model, update the XML data, and write out the XML data.

It then uses the JSON Serializer to write out the XML Data as JSON and read it back into the object model.

As you can see the JSON data includes the namespace data:
  "bs:bookstore": {
    "@xmlns:bs": "http://www.liquid-technologies.com/sample/bookstore";,
    "@xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance";,
    "bs:book": [
      {
        "@ISBN": "0596002521",
        "@price": 23.99,
        "@publicationdate": "2002-06-01",
        "bs:title": "XML Schema",
        "bs:author": {
          "bs:first-name": "Eric",
          "bs:last-name": "van der Vlist"
        },
        "bs:genre": "Reference"
      },
      {
        "@ISBN": "9780130655677",
        "@price": 7.99,
        "@publicationdate": "2001-12-07Z",
        "bs:title": "Definitive XML Schema",
        "bs:author": {
          "bs:first-name": "Priscilla",
          "bs:last-name": "Walmsley"
        },
        "bs:genre": "Reference"
      }
    ]
  }
}
Can you please provide an example where this is not the case?

0
Jean-Pierre Alvarez Replied
Apparently we don't have the same sample, I don't have the same fields for the BookstoreElm and the dlls of my solution "Liquid Technologies\Liquid XML Objects 2019\QuickStart\QuickStartCs.sln" doesn't even allow me to have access to the "LjSerializer" class.

I can see a small difference, all my generated objects inherit from LxBase which is not the case with BookstoreElm (but it's maybe due to my version of the sample which must be too old?).

In any case, here is the simplest example that does not work for me, I just replaced my object with yours:

        static void Main(string[] args)
        {
            BookstoreElm newBookstoreInstance = new BookstoreElm();

            string sampleJson;
            LjSerializer<BookstoreElm> jSerializer = new LjSerializer<BookstoreElm>();
            using (StringWriter jWriter = new StringWriter())
            {
                jSerializer.Serialize(jWriter, newBookstoreInstance);
                sampleJson = jWriter.ToString();
            }

            using (StringReader jReader = new StringReader(sampleJson))
            {
                BookstoreElm readBookstoreElm = jSerializer.Deserialize(jReader);
            }
        }


My main problem comes from the creation of an instance with "new", if I read an xml file containing all the necessary information I have no problem, but I need to create objects programmatically and be able to export them in json and read them back.





0
Jean-Pierre Alvarez Replied
Ok it seems that I have an acceptable solution, passing an XmlQualifiedName with the base node seems to be enough:

XmlQualifiedName qn = new XmlQualifiedName("AA", "Toto");

using (var writer = new StringWriter())
{
    serializer.Serialize(writer, totoelementName: qn);
    return writer.ToString();
}
With that it seems to retreive all the other namespaces it needs, in my case it is only one other namespace and it's added while serializing, so I guess it's ok!

Thanks for you help.
0
Liquid Support Replied
Employee Post
Thanks for your feedback, it looks like there is an issue where the Default Namespace is not getting written into the JSON document.

This issue will be fixed in the next point release.
0
Jean-Pierre Alvarez Replied
Actually the solution I gave is wrong, I have been doing so many tests that I didn't notice I was using the LxSerializer instead of the LjSerializer...

But I found another solution, I had to manually declare the required namespaces on the created object:
Toto elm = new Toto();
elm.UnprocessedAttributes.Add(new XAttribute(XNamespace.Xmlns + "AA", "Toto"));
elm.UnprocessedAttributes.Add(new XAttribute(XNamespace.Xmlns + "Intake", "XML_Intake"));
1
Liquid Support Replied
Employee Post Marked As Answer
This issue has now been fixed and is available in v20.2.6:

Reply to Thread