{"record":{"id":"d08eb96b28280837","repo":"JeffreySu/WeiXinMPSDK","slug":"expected-a-string-or-integer-json-value","errorCode":null,"errorMessage":"Expected a string or integer JSON value.","messagePattern":"Expected a string or integer JSON value\\.","errorType":"exception","errorClass":"JsonException","httpStatus":null,"severity":"error","filePath":"src/Senparc.Weixin.Work/Senparc.Weixin.Work/AdvancedAPIs/Meeting/MeetingPhoneJson.cs","lineNumber":190,"sourceCode":"        public IList<MeetingPhoneTempOpenIdItem> tmp_openid_list { get; set; }\n    }\n\n    internal sealed class MeetingStringOrNumberJsonConverter : JsonConverter<string>\n    {\n        public override string Read(ref Utf8JsonReader reader, Type typeToConvert,\n            JsonSerializerOptions options)\n        {\n            if (reader.TokenType == JsonTokenType.String)\n            {\n                return reader.GetString();\n            }\n\n            if (reader.TokenType == JsonTokenType.Number && reader.TryGetInt64(out var integer))\n            {\n                return integer.ToString(CultureInfo.InvariantCulture);\n            }\n\n            throw new JsonException(\"Expected a string or integer JSON value.\");\n        }\n\n        public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)\n            => writer.WriteStringValue(value);\n    }\n}\n","sourceCodeStart":172,"sourceCodeEnd":197,"githubUrl":"https://github.com/JeffreySu/WeiXinMPSDK/blob/be573f6f94bdbf718dd5f6cdecb137fbc7ff651e/src/Senparc.Weixin.Work/Senparc.Weixin.Work/AdvancedAPIs/Meeting/MeetingPhoneJson.cs#L172-L197","documentation":"A custom System.Text.Json converter in MeetingPhoneJson reads a JSON value that must be either a string or an integer and converts it to string. If the token is any other type (bool, object, array, null), Read throws JsonException(\"Expected a string or integer JSON value.\").","triggerScenarios":"Deserializing meeting/phone JSON where a normally string-or-number field arrives as bool/object/array/null — e.g. the API changed shape, or a caller supplies handcrafted JSON with an unexpected type for that field.","commonSituations":"WeCom returning error payloads or a new field type inside a meeting-phone response; test fixtures written with wrong types; deserializing with the wrong target model so the converter is applied to an unrelated token.","solutions":["Inspect the raw JSON at that field and confirm it is a string or number; fix the payload source or the test fixture","Map the field to a raw JsonElement/object property and normalize manually if the API is inconsistent","Use JsonElement.Type checks or a more lenient converter that coerces bool/null to string","Pin/check SDK version against the current WeCom Meeting API response schema"],"exampleFix":"// before\npublic string Phone { get; set; } // converter throws on bool/null\n// after\npublic JsonElement PhoneRaw { get; set; }\n[JsonIgnore] public string Phone => PhoneRaw.ValueKind == JsonValueKind.String ? PhoneRaw.GetString() : PhoneRaw.ToString();","handlingStrategy":"try-catch","validationCode":"if (token is JsonElement je && je.ValueKind is not (JsonValueKind.String or JsonValueKind.Number)) throw new JsonException($\"Unexpected kind {je.ValueKind}\");","typeGuard":"static bool IsStringOrNumber(JsonValueKind kind) => kind is JsonValueKind.String or JsonValueKind.Number;","tryCatchPattern":"try { var dto = JsonSerializer.Deserialize<MeetingPhoneResponse>(json); } catch (JsonException ex) { log.Error(ex, \"Unexpected token type in meeting-phone payload\"); }","preventionTips":["Log raw payloads on JsonException to spot API schema drift","Keep test fixtures type-accurate to the real API","Use JsonElement for fields the API sends inconsistently"],"tags":["json","deserialization","type-mismatch","wecom"],"backgroundTag":"type-mismatch","analyzedSha":"be573f6f94bdbf718dd5f6cdecb137fbc7ff651e","analyzedAt":"2026-09-12T10:01:50.733Z","contentChangedAt":"2026-09-12T10:01:50.733Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}