23

As i'm trying to access object values using JsonSerializer.Deserialize using debugger.
enter image description here

Here is my result which i'm having below.

  OtpData = ValueKind = Object : "{
        "OTP":"3245234",
        "UserName":"mohit840",
        "type":"SuperAdmin"
    }"

As i try to access it using var Data = JsonSerializer.Deserialize(OtpData) it gives me following error below.
enter image description here

How can i access the inside and get values of the following object.

"OTP":"3245234",
        "UserName":"mohit840",
        "type":"SuperAdmin"

Update :

        [AllowAnonymous]
        [HttpPost("ValidateOTP")]
        public IActionResult ValidOTP(dynamic OtpData)
        {
            bool Result = false;
            var Data = JsonSerializer.Deserialize(OtpData);            
            if (OtpData.type == "SuperAdmin")
            {
                Users _Users = _Context.Users.FirstOrDefault(j => j.Username == "");
                if (_Users != null)
                {
                    _Users.OTP = OtpData.OTP;                    
                    _Users.VerififedOTP = true;
                    _Context.SaveChanges();
                    Result = true;
                }
            }
            else
            {
                Staff _Staff = _Context.Staffs.FirstOrDefault(j => j.Username == "");
                if (_Staff != null)
                {
                    _Staff.OTP = OtpData.OTP;                    
                    _Staff.VerififedOTP = true;
                    _Context.SaveChanges();
                    Result = true;
                }
            }

            return Ok(new { Result = Result });
        } 

Update 2: As i'm posting this by Postman application.

{
    "OTP":"3245234",
    "UserName":"mohit840",
    "type":"SuperAdmin"
}
  • 2
    Why are you accepting a `dynamic` if you know it's a string and it only works if it's a string? You shouldn't be using dynamic typing unless you actually need it. Not having to deal with problems like this is one of the many reasons why. – Servy Jul 27 '20 at 19:05
  • So, what is the *actual type* of the `dynamic OptData`, returned by `OptData.GetType()`? It's probably not any of the types accepted by any of the overloads to [`JsonSerializer.Deserialize()`](https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializer.deserialize?view=netcore-3.1#System_Text_Json_JsonSerializer_Deserialize__1_System_String_System_Text_Json_JsonSerializerOptions_). But since you're using `dynamic` this sort of error can only be caught in runtime not compile time. – dbc Jul 27 '20 at 19:07
  • @dbc i'll added code i just need to access those values how can i do so ...? –  Jul 27 '20 at 19:08
  • I'll update again for the actual type. –  Jul 27 '20 at 19:10
  • @dbc even if i use object keyword i t still shows me same result. –  Jul 27 '20 at 19:14
  • 1
    @NamanKumar You will not get a runtime binder exception if you're not using `dynamic`. That exception is specific to dynamically compiling code. If the types of your code aren't valid, they'll be compiler errors instead. – Servy Jul 27 '20 at 19:19
  • @Servy How can i access these objects dynamically as i don't want to hard code them which i could have used before. –  Jul 27 '20 at 19:40
  • Did you ever determine the actual, concrete type of `OtpData`? You've tagged this with both [tag:json.net] and [tag:system.text.json] so we really have no way of guessing what that really is. I mean specifically what is returned if you examine the value of `OtpData.GetType().FullName` in the debugger. – dbc Jul 27 '20 at 19:41
  • ok @dbc i'll update again –  Jul 27 '20 at 19:41
  • @NamanKumar Your input is always a string. It's never anything else. Making it `dynamic` doesn't change that at all. The documentation of whatever deserialier you're using will cover how to inspect objects that don't have a static structure, but that's based on the output, not the input. – Servy Jul 27 '20 at 20:21

6 Answers6

10

From new release of Asp.net Core 3.0 Microsoft has come with System.Text.Json which introduce new JsonElement ValueKind so ValueKind is from System.Text.Json library and JsonConvert is from Newtonsoft library.

Resolution :-

it is possible that you have mixed both the library while Serializing the object you may have used Newtonsoft.Json and while Deserilizing you may have used System.Text.Json or vice versa.

Ankit Mori
  • 705
  • 14
  • 23
8
public async Task<dynamic> PostAsync([FromBody] Object post)
{
     var data = JsonConvert.DeserializeObject<dynamic>(post.ToString());
realPro
  • 1,713
  • 3
  • 22
  • 34
  • This is a good and working answer which I was looking for too. But instead of public async Task, public async Task would be better in web api scenarios. – Venugopal M Oct 04 '22 at 05:02
3

ASP.Net core uses inbuilt System.Text.Json based JsonConverter for binding the model from json input that is sent. If you are using Newtonsoft Json in your project, you need to configure this to use it for the model binding.

For that you need to install the nuget package "Microsoft.AspNetCore.Mvc.NewtonsoftJson" and add the line "builder.Services.AddControllers().AddNewtonsoftJson();" to Program.cs. This will serilaize the expando object properly by name and value.

Prasad
  • 31
  • 1
  • Thank you very much - I was trying to implement a PATCH with optional (nullable) values using an OpenApi / client generated from .net's "Connected Services". This fixed my issue. – Luciox Nov 25 '22 at 11:31
0

Refer System.Text.Json.JsonSerializer instead of newton soft json serializer

class OTPData{ public string OTP {get;set} ....... }

var result = System.Text.Json.JsonSerializer.Deserialize<OTPData> 
(response.ToString());

string otp = result.OTP;
string username = result.UserName;
string type = result.type;
Dinesh V
  • 31
  • 6
0

The ValueKind is json data in System.Text.Json format. We can convert it to any type using Newtonsoft.Json as below:

public class OtpData
{
  public string Otp { get; set; } 
  public string UserName { get; set; } 
  public string Type { get; set; } 
}
    
public OtpData GetOtpData(object otpData)
{
  var jsonString = ((System.Text.Json.JsonDocument)otpData).RootElement.GetRawText();
  return JsonConvert.DeserializeObject<OtpData>(jsonString);
}
-1
public class OtpData { 
[JsonPropertyName("OTP")] 
public string Otp { get; set; } 
[JsonPropertyName("UserName")] 
public string UserName { get; set; } 
[JsonPropertyName("type")] 
public string Type { get; set; } 
} 
public IActionResult ValidOTP(OtpData data) 
{ 
bool result = false; 
if (data.Type.ToString() == "SuperAdmin") { } 
} 
vinit jain
  • 222
  • 2
  • 3