skip to Main Content

I’m getting a response string from Azure DevOps REST API that contain mostly JSON, with some XML sprinkled into a few property values. I build a number of C# classes replicating the JSON structure of the response, in order to deserialize the response.

When

var response = client.Get(request);
if (response.StatusCode == HttpStatusCode.OK
    && response.Content != null)
{
    return JsonSerializer.Deserialize<T>(response.Content);
}

reaches the XML in

public class Fields
{
    ...
    [JsonPropertyName("Microsoft.VSTS.TCM.Steps")]
    public Steps MicrosoftVSTSTCMSteps { get; set; }
}

I get a

System.Text.Json.JsonException: 'The JSON value could not be converted to ADO.Response.Steps. Path: $.fields['Microsoft.VSTS.TCM.Steps'] | LineNumber: 0 | BytePositionInLine: 5149.'

The Steps class is defined like

[XmlRoot(ElementName = "steps")]
public class Steps
{
    [XmlElement(ElementName = "step")]
    public Step[] Step { get; set; }

    [XmlAttribute(AttributeName = "id")]
    public string Id { get; set; }

    [XmlAttribute(AttributeName = "last")]
    public string Last { get; set; }

    ...
}

An exerpt of the incomming JSON/XML string looks like this:

{
  ...
  "Microsoft.VSTS.TCM.Steps":"<?xml version="1.0"?><steps last="5" id="0"><step id="2"  type="ActionStep"><parameterizedString isformatted="true"></parameterizedString><description /></step></steps><xml/>
  ...
}

How do I deserialize the JSON and the XML without detaching the Steps class from the hierarchy by e.g keeping the XML as a string in the deserialized JSON?

I’m looking to avoid post processing like this

XmlSerializer XmlSerializer = new XmlSerializer(typeof(Steps));
Steps steps = (Steps)XmlSerializer.Deserialize(new StringReader(resp.fields.MicrosoftVSTSTCMSteps));

2

Answers


  1. See solution below

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Xml;
    using System.Xml.Serialization;
    using System.Xml.Schema;
    using System.Text.Json;
    
    namespace ConsoleApp10
    {
        class Program
        {
            const string FILENAME = @"c:tempmyprogram.xml";
            static void Main(string[] args)
            {
     
    
            }
        }
        [XmlRoot(ElementName = "steps")]
        public class Steps : IXmlSerializable
        {
            [XmlElement(ElementName = "step")]
            public Step[] Step { get; set; }
    
            [XmlAttribute(AttributeName = "id")]
            public string Id { get; set; }
    
            [XmlAttribute(AttributeName = "last")]
            public string Last { get; set; }
    
            public JsonElement json { get; set; }
    
            [XmlText]
            public string text
            {
                get { return JsonSerializer.Serialize(json); }
                set { json = (JsonElement) JsonSerializer.Deserialize(value, typeof(JsonElement)); }
            }
    
            public void WriteXml(XmlWriter writer)
            {
            }
    
            public void ReadXml(XmlReader reader)
            {
            }
    
            public XmlSchema GetSchema()
            {
                return (null);
            }
    
        }
        public class Step
        {
    
        }
    
    }
    
    Login or Signup to reply.
  2. It is (as the most json tasks too) much easier to do with Newtonsoft.Json

    
    var jObj =  JObject.Parse(response.Content);
    
    Fields fields  = jObj.ToObject<Fields>();
    
    var json = JsonConvert.SerializeXNode(XElement.Parse((string)jObj["Microsoft.VSTS.TCM.Steps"]));
    
    fields.MicrosoftVSTSTCMSteps = JsonConvert.DeserializeObject<Root>(json).steps;
    

    classes

    public class Fields
    {
       // another properties
    
        [JsonIgnore]
        public Steps MicrosoftVSTSTCMSteps { get; set; }
    }
    
    public class Root
    {
        public Steps steps { get; set; }
    }
    
    public class ParameterizedString
    {
        [JsonProperty("@isformatted")]
        public string Isformatted { get; set; }
    }
    
    public class Step
    {
        [JsonProperty("@id")]
        public string Id { get; set; }
    
        [JsonProperty("@type")]
        public string Type { get; set; }
        
       [JsonProperty("parameterizedString")]
        public ParameterizedString ParameterizedString { get; set; }
    }
    
    public class Steps
    {
        [JsonProperty("@last")]
        public string Last { get; set; }
    
        [JsonProperty("@id")]
        public string Id { get; set; }
        
        [JsonProperty("step")]
        public Step Step { get; set; }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search