c# Newtonsoft json:如何反序列化 json 并获取浮点字段的原始字符串
c# Newtonsoft json: how to deserialize json and get raw strings for float fields
考虑 json 字符串:
var json = "{\"myfield\":5e-0000006}";
我想反序列化 json,并将字段“myfield”作为原始字符串获取。
示例:
JToken tok = <Deserialize> // how do this??
var val = tok["myfield"].ToString(); // need get "5e-0000006"
我需要获取原始字符串中的精确字符串值(例如“5e-0000006”,但它可以是任何有效的浮点字符串)。
因为你想要一个精确的字符串,而你得到的 json 实际上是一个数字(这意味着 5e-0000006
将等于 5e-6
)我建议使用正则表达式:
string json = "{\"myfield\":5e-0000006}";
Regex regex = new Regex("(?<=:)[^}]+");
string result = regex.Match(json).Value;
解释:
(?<=:)
往后看冒号 (:
)
[^}]+
匹配任何不是右花括号 (}
) 的字符一次或多次。
这应该会为您提供精确字符串形式的值。
更新:
如果您想根据 myfield
变量进行匹配,您可以扩展正则表达式以包含该信息:
string json = "{\"myfield\":5e-0000006}";
Regex regex = new Regex("(?<=\"myfield\":)[^}]+");
string result = regex.Match(json).Value;
现在您只会看到前面有 \"myfield\"
的行 - 如果您有很多行。
你当然可以用变量替换\"myfield\"
,像这样:
string json = "{\"myfield\":5e-0000006}";
string myvar = "myfield";
Regex regex = new Regex("(?<=\"" + myvar + "\":)[^}]+");
string result = regex.Match(json).Value;
一些信息和灵感来自:
- You don't need to write any converters, just use the JRaw type as follows:
- 文档:This sample deserializes JSON to an object.
static void Main(string[] args)
{
var json = "{\"myfield\":5e-0000006}";
MyJson j = JsonConvert.DeserializeObject<MyJson>(json);
string mf = j.myfield;
Console.WriteLine(mf);
}
public class MyJson
{
[JsonProperty("myfield")]
public string myfield { get; set; }
}
这将输出:5e-0000006
而且我还在想为什么我不使用 JRaw
...
我最终围绕 System.Text.Json
创建了一个简单的包装器
class MyJToken {
JsonElement cur;
string fieldName;
public bool IsNull { get; private set; }
public MyJToken(JsonElement cur, string fieldName) {
this.cur = cur;
this.fieldName = fieldName;
}
public MyJToken() {
IsNull = true;
}
public override string ToString() {
if (IsNull) {
return "null";
}
return cur.ToString();
}
public static MyJToken Parse(string json) {
JsonDocument doc = JsonDocument.Parse(json);
return new MyJToken(doc.RootElement, "root");
}
public IEnumerable<(string, MyJToken)> EnumKeyVal() {
foreach(var elem in cur.EnumerateObject()) {
yield return (elem.Name, new MyJToken(elem.Value, elem.Name));
}
yield break;
}
public IEnumerable<MyJToken> EnumList() {
foreach (var elem in cur.EnumerateArray()) {
yield return new MyJToken(elem, "");
}
yield break;
}
public MyJToken get(string name) {
return this[name];
}
public MyJToken this[string key] {
get {
if (!cur.TryGetProperty(key, out var value))
return new MyJToken();
return new MyJToken(value, key);
}
}
public MyJToken this[int key] {
get => new MyJToken(cur[key], key.ToString());
}
void SayNotFound() {
throw new Exception($"Filed {fieldName} not found");
}
public string STR() {
if (IsNull) SayNotFound();
return cur.GetString();
}
public string STR(string def) {
if (IsNull) return def;
return STR();
}
public string RAW() {
if (IsNull) SayNotFound();
return cur.GetRawText();
}
public string RAW(string def) {
if (IsNull) return def;
return RAW();
}
public decimal DEC() {
if (IsNull) SayNotFound();
return cur.GetDecimal();
}
public decimal DEC(decimal def) {
if (IsNull) return def;
return DEC();
}
public long LONG() {
if (IsNull) SayNotFound();
return cur.GetInt64();
}
public long LONG(long def) {
if (IsNull) return def;
return LONG();
}
}
现在我可以得到任何我想要的东西了:
var json = "{\"myfield\":5e-0000006}";
var root = MyJToken.Parse(json);
var tok = root["myfield"];
Console.WriteLine($"num={tok.DEC()} raw={tok.RAW()}");
考虑 json 字符串:
var json = "{\"myfield\":5e-0000006}";
我想反序列化 json,并将字段“myfield”作为原始字符串获取。 示例:
JToken tok = <Deserialize> // how do this??
var val = tok["myfield"].ToString(); // need get "5e-0000006"
我需要获取原始字符串中的精确字符串值(例如“5e-0000006”,但它可以是任何有效的浮点字符串)。
因为你想要一个精确的字符串,而你得到的 json 实际上是一个数字(这意味着 5e-0000006
将等于 5e-6
)我建议使用正则表达式:
string json = "{\"myfield\":5e-0000006}";
Regex regex = new Regex("(?<=:)[^}]+");
string result = regex.Match(json).Value;
解释:
(?<=:)
往后看冒号 (:
)
[^}]+
匹配任何不是右花括号 (}
) 的字符一次或多次。
这应该会为您提供精确字符串形式的值。
更新:
如果您想根据 myfield
变量进行匹配,您可以扩展正则表达式以包含该信息:
string json = "{\"myfield\":5e-0000006}";
Regex regex = new Regex("(?<=\"myfield\":)[^}]+");
string result = regex.Match(json).Value;
现在您只会看到前面有 \"myfield\"
的行 - 如果您有很多行。
你当然可以用变量替换\"myfield\"
,像这样:
string json = "{\"myfield\":5e-0000006}";
string myvar = "myfield";
Regex regex = new Regex("(?<=\"" + myvar + "\":)[^}]+");
string result = regex.Match(json).Value;
一些信息和灵感来自:
- You don't need to write any converters, just use the JRaw type as follows:
- 文档:This sample deserializes JSON to an object.
static void Main(string[] args)
{
var json = "{\"myfield\":5e-0000006}";
MyJson j = JsonConvert.DeserializeObject<MyJson>(json);
string mf = j.myfield;
Console.WriteLine(mf);
}
public class MyJson
{
[JsonProperty("myfield")]
public string myfield { get; set; }
}
这将输出:5e-0000006
而且我还在想为什么我不使用 JRaw
...
我最终围绕 System.Text.Json
创建了一个简单的包装器class MyJToken {
JsonElement cur;
string fieldName;
public bool IsNull { get; private set; }
public MyJToken(JsonElement cur, string fieldName) {
this.cur = cur;
this.fieldName = fieldName;
}
public MyJToken() {
IsNull = true;
}
public override string ToString() {
if (IsNull) {
return "null";
}
return cur.ToString();
}
public static MyJToken Parse(string json) {
JsonDocument doc = JsonDocument.Parse(json);
return new MyJToken(doc.RootElement, "root");
}
public IEnumerable<(string, MyJToken)> EnumKeyVal() {
foreach(var elem in cur.EnumerateObject()) {
yield return (elem.Name, new MyJToken(elem.Value, elem.Name));
}
yield break;
}
public IEnumerable<MyJToken> EnumList() {
foreach (var elem in cur.EnumerateArray()) {
yield return new MyJToken(elem, "");
}
yield break;
}
public MyJToken get(string name) {
return this[name];
}
public MyJToken this[string key] {
get {
if (!cur.TryGetProperty(key, out var value))
return new MyJToken();
return new MyJToken(value, key);
}
}
public MyJToken this[int key] {
get => new MyJToken(cur[key], key.ToString());
}
void SayNotFound() {
throw new Exception($"Filed {fieldName} not found");
}
public string STR() {
if (IsNull) SayNotFound();
return cur.GetString();
}
public string STR(string def) {
if (IsNull) return def;
return STR();
}
public string RAW() {
if (IsNull) SayNotFound();
return cur.GetRawText();
}
public string RAW(string def) {
if (IsNull) return def;
return RAW();
}
public decimal DEC() {
if (IsNull) SayNotFound();
return cur.GetDecimal();
}
public decimal DEC(decimal def) {
if (IsNull) return def;
return DEC();
}
public long LONG() {
if (IsNull) SayNotFound();
return cur.GetInt64();
}
public long LONG(long def) {
if (IsNull) return def;
return LONG();
}
}
现在我可以得到任何我想要的东西了:
var json = "{\"myfield\":5e-0000006}";
var root = MyJToken.Parse(json);
var tok = root["myfield"];
Console.WriteLine($"num={tok.DEC()} raw={tok.RAW()}");