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;

一些信息和灵感来自:

        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()}");