Jsonconvert - 如何定义结构

Posted

技术标签:

【中文标题】Jsonconvert - 如何定义结构【英文标题】:Jsonconvert - How to define structure 【发布时间】:2021-03-24 11:02:13 【问题描述】:

晚上好。我有一个这样的 XML 结构:

string cRet = "<bands>";

cRet += "<artist>";

cRet += "<name>";
cRet += "Vasco";
cRet += "</name>";

cRet += "<lp>";
cRet += "<namelp>";
cRet += "Bollicine";
cRet += "</namelp>";
cRet += "<songs>";
cRet += "<song>";
cRet += "Bollicine";
cRet += "</song>";
cRet += "<song>";
cRet += "Vita Spericolata";
cRet += "</song>";
cRet += "<song>";
cRet += "Giocala";
cRet += "</song>";
cRet += "</songs>";
cRet += "</lp>";

cRet += "<lp>";
cRet += "<namelp>";
cRet += "Gli SPari Sopra";
cRet += "</namelp>";
cRet += "<songs>";
cRet += "<song>";
cRet += "Gli SPari Sopra";
cRet += "</song>";
cRet += "<song>";
cRet += "Gabri";
cRet += "</song>";
cRet += "<song>";
cRet += "Lo Show";
cRet += "</song>";
cRet += "</songs>";
cRet += "</lp>";

cRet += "</artist>";

cRet += "</bands>";


var serializer = new XmlSerializer(typeof(Root));
var root = (Root)serializer.Deserialize(new StringReader(cRet));
string cJson = JsonConvert.SerializeObject(root, Newtonsoft.Json.Formatting.Indented);

我定义:

[XmlRoot("bands"), JsonObject]
public class Root

    [XmlElement, JsonProperty]
    public string name  get; set; 

    [XmlElement, JsonProperty]
    public string albumName  get; set; 

    [XmlElement, JsonProperty]
    public string song  get; set; 


我得到:

 "name": null, "albumName": null, "song": null 

如果我只使用一个级别,我会得到完美的结果。 如何定义“艺术家”和“专辑”?

【问题讨论】:

你调试过你的代码吗? root 在 XML 反序列化之后是否包含任何内容?对于它的价值,这是一种创建 XML 字符串(所有字符串连接)的低效方式 你想要的输出是什么? 【参考方案1】:

您有 Visual Studio 2017/2019 吗?如果是这样,您可以 Generate Class From JSON or XML in Visual Studio 。正确定义类后,您应该可以使用 Newtonsoft.Json 创建您的 json。

要从 XML 创建类,请执行以下操作:

创建您的示例 XML:

注意:如果您的 XML 中的任何元素包含多个元素,请确保您的示例数据包含多个元素。

<bands>
  <artist>
    <name>Vasco</name>
    <lp>
      <namelp>Bollicine</namelp>
      <songs>
        <song>Bollicine</song>
        <song>Vita Spericolata</song>
        <song>Giocala</song>
      </songs>
    </lp>
  </artist>
  <artist>
    <name>Other Artist</name>
    <lp>
      <namelp>Other Artist album name</namelp>
      <songs>
        <song>Song 1</song>
        <song>Song 2</song>
      </songs>
    </lp>
  </artist>
</bands>

打开 Visual Studio 2017(或 2019)

创建新项目(文件 => 新项目 => ...)

添加using语句:using System.Xml.Serialization;

创建新类(Project => Add Class...)名称:bands

在记事本中打开您的示例 XML。

突出显示 XML,右键单击并选择 复制

在 VS 菜单中,点击编辑

选择选择性粘贴

选择将 XML 粘贴为类

您将获得以下信息:

// NOTE: Generated code may require at least .NET Framework 4.5 or .NET Core/Standard 2.0.
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class bands


    private bandsArtist[] artistField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("artist")]
    public bandsArtist[] artist
    
        get
        
            return this.artistField;
        
        set
        
            this.artistField = value;
        
    


/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class bandsArtist


    private string nameField;

    private bandsArtistLP lpField;

    /// <remarks/>
    public string name
    
        get
        
            return this.nameField;
        
        set
        
            this.nameField = value;
        
    

    /// <remarks/>
    public bandsArtistLP lp
    
        get
        
            return this.lpField;
        
        set
        
            this.lpField = value;
        
    


/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class bandsArtistLP


    private string namelpField;

    private string[] songsField;

    /// <remarks/>
    public string namelp
    
        get
        
            return this.namelpField;
        
        set
        
            this.namelpField = value;
        
    

    /// <remarks/>
    [System.Xml.Serialization.XmlArrayItemAttribute("song", IsNullable = false)]
    public string[] songs
    
        get
        
            return this.songsField;
        
        set
        
            this.songsField = value;
        
    

我稍微修改/重构了代码,最终得到了下面的代码。我改变了类名的大小写。此外,为了按所需顺序对相同深度的元素进行排序,我为某些类添加了接口(如.NET Serialization Ordering 中所述)

/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false, ElementName = "bands")]
public partial class Bands


    [System.Xml.Serialization.XmlElementAttribute("artist")]
    public List<BandsArtist> artist  get; set;  = new List<BandsArtist>(); 


public interface IBandsArtist

    string name  get; set; 
    List<BandsArtistLP> lp  get; set; 



[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class BandsArtist : IBandsArtist

    [XmlElement("name")]
    public string name  get; set; 


    [System.Xml.Serialization.XmlElementAttribute("lp")]
    public List<BandsArtistLP> lp  get; set;  = new List<BandsArtistLP>();
    


public interface IBandsArtistLP

    string namelp  get; set; 
    List<string> songs  get; set; 


[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class BandsArtistLP : IBandsArtistLP


    [XmlElement("namelp")]
    public string namelp  get; set; 

    [XmlArrayItemAttribute("song", IsNullable = false)]
    public List<string> songs  get; set;  = new List<string>();
    

使用 Newtonsoft.json 序列化“bands”类(其中“myBands”是包含您的数据的“bands”类的实例)

string cJson = JsonConvert.SerializeObject(myBands, Newtonsoft.Json.Formatting.Indented);

生成的 json 为


  "artist": [
    
      "name": "Vasco",
      "lp": [
        
          "namelp": "Bollicine",
          "songs": [
            "Bollicine",
            "Vita Spericolata",
            "Giocala"
          ]
        
      ]
    ,
    
      "name": "Other Artist",
      "lp": [
        
          "namelp": "Other Artist album name",
          "songs": [
            "Song 1",
            "Song 2"
          ]
        
      ]
    
  ]

【讨论】:

以上是关于Jsonconvert - 如何定义结构的主要内容,如果未能解决你的问题,请参考以下文章

JsonConvert.SerializeObject - 自定义 ContracteResolver 不为多次调用调用 CreateProperty

Newtonsoft.Json.JsonConvert 从同一个类中序列化和反序列化

如何使用 JSONConvert 将变量 Result 转换为对象?

如何使用 JsonConvert 从包含空数组的 JSON 字符串中获取 DataTable?

如何调用 JsonConvert.DeserializeObject 并禁用通过 [JsonConverter] 应用于基本类型的 JsonConverter?

如何在 Json.Net 中的 JsonConvert DeserializeObject 之后获取所有不存在的键?