[英]How to convert JSON to YAML using YamlDotNet
我正在嘗試使用 YamlDotNet 將 JSON 轉換為 YAML。 這是我的代碼:
class Program
{
static void Main(string[] args)
{
var json = "{\"swagger\":\"2.0\",\"info\":{\"title\":\"UberAPI\",\"description\":\"MoveyourappforwardwiththeUberAPI\",\"version\":\"1.0.0\"},\"host\":\"api.uber.com\",\"schemes\":[\"https\"],\"basePath\":\"/v1\",\"produces\":[\"application/json\"]}";
var swaggerDocument = JsonConvert.DeserializeObject(json);
var serializer = new YamlDotNet.Serialization.Serializer();
using (var writer = new StringWriter())
{
serializer.Serialize(writer, swaggerDocument);
var yaml = writer.ToString();
Console.WriteLine(yaml);
}
}
}
這是我提供的 JSON:
{
"swagger":"2.0",
"info":{
"title":"UberAPI",
"description":"MoveyourappforwardwiththeUberAPI",
"version":"1.0.0"
},
"host":"api.uber.com",
"schemes":[
"https"
],
"basePath":"/v1",
"produces":[
"application/json"
]
}
這是我期望的 YAML:
swagger: '2.0'
info:
title: UberAPI
description: MoveyourappforwardwiththeUberAPI
version: 1.0.0
host: api.uber.com
schemes:
- https
basePath: /v1
produces:
- application/json
但是,這是我得到的輸出:
swagger: []
info:
title: []
description: []
version: []
host: []
schemes:
- []
basePath: []
produces:
- []
我不知道為什么所有屬性都是空數組。
我也嘗試過這樣的類型化反序列化和序列化:
var specification = JsonConvert.DeserializeObject<SwaggerDocument>(json);
...
serializer.Serialize(writer, swaggerDocument, typeof(SwaggerDocument));
但這會產生
{}
任何幫助深表感謝。
您實際上不需要將 JSON 反序列化為強類型對象,您也可以使用動態 Expando 對象將 JSON 轉換為 YAML。 這是一個小例子:-
var json = @"{
'Name':'Peter',
'Age':22,
'CourseDet':{
'CourseName':'CS',
'CourseDescription':'Computer Science',
},
'Subjects':['Computer Languages','Operating Systems']
}";
var expConverter = new ExpandoObjectConverter();
dynamic deserializedObject = JsonConvert.DeserializeObject<ExpandoObject>(json, expConverter);
var serializer = new YamlDotNet.Serialization.Serializer();
string yaml = serializer.Serialize(deserializedObject);
您可以在此處查看這兩種方法的詳細說明,即使用強類型對象和動態對象。
您可以將JObject
轉換為 YamlDotNet 可以序列化的更簡單的對象:
class Program
{
static void Main(string[] args)
{
var json = "{\"swagger\":\"2.0\",\"info\":{\"title\":\"UberAPI\",\"description\":\"MoveyourappforwardwiththeUberAPI\",\"version\":\"1.0.0\"},\"host\":\"api.uber.com\",\"schemes\":[\"https\"],\"basePath\":\"/v1\",\"produces\":[\"application/json\"]}";
var swaggerDocument = ConvertJTokenToObject(JsonConvert.DeserializeObject<JToken>(json));
var serializer = new YamlDotNet.Serialization.Serializer();
using (var writer = new StringWriter())
{
serializer.Serialize(writer, swaggerDocument);
var yaml = writer.ToString();
Console.WriteLine(yaml);
}
}
static object ConvertJTokenToObject(JToken token)
{
if (token is JValue)
return ((JValue)token).Value;
if (token is JArray)
return token.AsEnumerable().Select(ConvertJTokenToObject).ToList();
if (token is JObject)
return token.AsEnumerable().Cast<JProperty>().ToDictionary(x => x.Name, x => ConvertJTokenToObject(x.Value));
throw new InvalidOperationException("Unexpected token: " + token);
}
}
我認為 json 反序列化返回JObject
時存在問題。 看起來 yaml 序列化程序不喜歡它。
正如你提到的,我使用了指定類型的反序列化JsonConvert.DeserializeObject<SwaggerDocument>(json)
這就是我得到的
Swagger: 2.0
Info:
Title: UberAPI
Description: MoveyourappforwardwiththeUberAPI
Version: 1.0.0
Host: api.uber.com
Schemes:
- https
BasePath: /v1
Produces:
- application/json
這是我的全部代碼:
class Program
{
static void Main(string[] args)
{
var json = "{\"Swagger\":\"2.0\",\"Info\":{\"Title\":\"UberAPI\",\"Description\":\"MoveyourappforwardwiththeUberAPI\",\"Version\":\"1.0.0\"},\"Host\":\"api.uber.com\",\"Schemes\":[\"https\"],\"BasePath\":\"/v1\",\"Produces\":[\"application/json\"]}";
var swaggerDocument = JsonConvert.DeserializeObject<SwaggerDocument>(json);
var serializer = new YamlDotNet.Serialization.Serializer();
using (var writer = new StringWriter())
{
serializer.Serialize(writer, swaggerDocument);
var yaml = writer.ToString();
Console.WriteLine(yaml);
}
}
}
public class Info
{
public string Title { get; set; }
public string Description { get; set; }
public string Version { get; set; }
}
public class SwaggerDocument
{
public string Swagger { get; set; }
public Info Info { get; set; }
public string Host { get; set; }
public List<string> Schemes { get; set; }
public string BasePath { get; set; }
public List<string> Produces { get; set; }
}
更新
這里有兩個問題。
使用字段反序列化類時,默認情況下, json.net
在執行此工作時不會考慮它們。 為此,我們必須通過創建自定義合約解析器來自定義反序列化過程。 我們可以很容易地做到這一點
var swaggerDocument = JsonConvert.DeserializeObject<SwaggerDocument>(json, new JsonSerializerSettings
{
ContractResolver = new MyContractResolver()
});
public class MyContractResolver : DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
var props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Select(p => base.CreateProperty(p, memberSerialization))
.Union(type.GetFields(BindingFlags.Public | BindingFlags.Instance)
.Select(f => base.CreateProperty(f, memberSerialization)))
.ToList();
props.ForEach(p => { p.Writable = true; p.Readable = true; });
return props;
}
}
當我們想用字段序列化類時,還有第二個問題:來自字段的值不會包含在 yaml 結果中。 我還沒有想出如何處理這個問題。
您是否必須使用Swashbuckle.Swagger
類型,或者您可以為此類型創建包裝器/裝飾器/DTO?
我希望它能幫助你。
FWIW 我編寫了一個 nuget 庫來使 YamlDotNet 與 Json.Net 一起工作,尊重所有 JSON.net 序列化屬性。
var yaml = YamlConvert.SerializeObject(obj);
var obj2 = YamlConvert.DeserializeObject<T>(yaml);
它的工作原理是為 JTokens (JObject/JArray/JValue) 添加一個 YamlDotNet 類型的序列化類
var serializer = new SerializerBuilder()
.WithTypeConverter(new JTokenYamlConverter())
.Build();
使用Cinchoo ETL - 一個開源庫可以輕松地進行此類轉換。
using (var r = new ChoJSONReader("*** YOUR JSON FILEPATH ***"))
{
using (var w = new ChoYamlWriter("*** YAML FILE OUTPUT PATH ***").SingleDocument())
{
w.Write(r);
}
}
輸出:
swagger: 2.0
info:
title: UberAPI
description: MoveyourappforwardwiththeUberAPI
version: 1.0.0
host: api.uber.com
schemes:
- https
basePath: /v1
produces:
- application/json
示例小提琴: https : //dotnetfiddle.net/rbOD0o
免責聲明:我是這個庫的作者。
我正在使用以下代碼從 JSON 構建 Yaml 元素並將其寫入文件。
這是代碼:
public static void BuildParametrizedYAML(string element, string element1)
{
var jsonBreakers = @"
{
'watchers' : {
'timer' : '10',
'watcherPool' : '5',
's3fileExtension' : '.avr.gz',
'maxRetriesTask' : '3',
'telemetryFolder' : '/data',
'telemetryProcessor' : {
'url' : '"+ element1 + @"'
},
'breakers' :
[
{
'breakerId' : 'COMMANDER',
'firstRetryTimeout' : '1000',
'secondRetryTimeout' : '6000',
'retries' : '5'
},
{
'breakerId' : 'PROCESSOR',
'firstRetryTimeout' : '1000',
'secondRetryTimeout' : '6000',
'retries' : '30'
}
],
'servers' :
[
{
'serverId' : 'vmax',
'url' : '"+ element + @"'
}
]
}
}";
var expConverter = new ExpandoObjectConverter();
dynamic deserializedObject = JsonConvert.DeserializeObject<ExpandoObject>(jsonBreakers, expConverter);
var serializer = new Serializer();
string JSONContent = serializer.Serialize(deserializedObject);
var streamLoad = new StringReader(JSONContent);
var stream = new YamlStream();
stream.Load(streamLoad);
using (TextWriter writer = File.CreateText("application.yml"))
{
stream.Save(writer, false);
}
}
這是輸出:
watchers:
timer: 10
watcherPool: 5
s3fileExtension: .avr.gz
maxRetriesTask: 3
telemetryFolder: /data
telemetryProcessor:
url: TELEMETRYPROCESSORURL
breakers:
- breakerId: COMMANDER
firstRetryTimeout: 1000
secondRetryTimeout: 6000
retries: 5
- breakerId: PROCESSOR
firstRetryTimeout: 1000
secondRetryTimeout: 6000
retries: 30
servers:
- serverId: vmax
url: TELEMETRYWATCHERVMAXURL
...
請隨意寫信給我。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.