0

I have these model classes:

public class TransactionInfo
{
        public int request_id { get; set; }
        public DateTime request_date { get; set; }
        public double request_amount { get; set; }
        public int request_count { get; set; }
        public string national_code { get; set; }
        public DateTime nav_date { get; set; }
        public DateTime approved_date { get; set; }
        public double nav_value { get; set; }
        public string request_type { get; set; }
        public string request_state { get; set; }
        public string username { get; set; }
        public string request_serial { get; set; }
        public double request_fixed_wage { get; set; }
        public double request_variable_wage { get; set; }
}

public class TransactionMessage
{
        public TransactionInfo info { get; set; }
        public string message_date { get; set; }
        public string message_type { get; set; }
        public string portfolio_code { get; set; }
        public string workingday_date { get; set; }
        public string event_type { get; set; }
}

And here is my JSON data:

"{\"info\":{\"request_id\":148786,\"request_date\":\"2022-09-04T12:23:00\",\"request_amount\":123.0,\"request_count\":-1,\"national_code\":\"1045451\",\"nav_date\":\"2022-09-05T00:00:00\",\"approved_date\":\"2022-09-06T00:00:00\",\"nav_value\":0.0,\"request_type\":\"SUBSCRIPTION\",\"request_state\":\"PENDING\",\"username\":\"a.daszarrin\",\"request_serial\":\"123\",\"request_fixed_wage\":0.0,\"request_variable_wage\":0.0},\"event_type\":\"REQUEST_CREATED\",\"message_date\":\"2022-09-04 12:23:26\",\"message_type\":\"REQUEST\",\"portfolio_code\":\"10851\",\"workingday_date\":\"2022-09-04\"}"

My code:

  var rawData = JsonSerializer.Deserialize<TransactionMessage>(Value);

When I want to convert value to model I get this error :

System.Text.Json.JsonException: 'The JSON value could not be converted to fund.api.TransactionMessage. Path: $ | LineNumber: 0 | BytePositionInLine: 599.'

StackTrace

at System.Text.Json.ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(Type propertyType)
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value) at System.Text.Json.Serialization.JsonConverter1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
at System.Text.Json.Serialization.JsonConverter1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state) at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan1 utf8Json, JsonTypeInfo jsonTypeInfo, Nullable1 actualByteCount) at System.Text.Json.JsonSerializer.Deserialize[TValue](ReadOnlySpan1 utf8Json, JsonSerializerOptions options)
at fund.api.FundHostedService.<b__8_0>d.MoveNext() in D:\gitProjects\Orbis.fund.api\FundHostedService.cs:line 74
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at infrastructure.Queue.RabbitMQ.RabbitMQConsumer.<>c__DisplayClass4_0.<b__0>d.MoveNext() in D:\infrastructure\Queue\RabbitMQ\RabbitMQConsumer.cs:line 33

As a note when I convert the array to test I get the exact value of json:

var data = System.Text.Encoding.Default.GetString((eventArgs.Body.ToArray()));

Update 1 - here is my consumer of my rabbit mq:

private Task StartFundTransactionResultConsuming()
      => _rabbitMQConsumer.Consume(QUEUE_TRANSACTION_CONSUMER_NAME, async (payload) =>
         {
             var rawData = JsonSerializer.Deserialize<TransactionMessage>(payload);
             if (rawData is null) 
                 return;
             Log.Logger.Information($"fund.api.TransactionConsumer, has Data: {JsonSerializer.Serialize(rawData)}");

             var redisResult = await _cache.KeyDeleteAsync(nameof(TransactionsEntity) + $":{rawData.info.national_code}");

             if (!redisResult)
             {
                 Serilog.Log.Logger.Error($"fund.api.TransactionConsumer, redis can't delete transaction for customer: {rawData.info.national_code}");
             }
         });

And here is my consumer :

public Task Consume(string topic, Func<byte[], Task> callback)
{
    ConnectToRabbitMq();
    var consumer = new AsyncEventingBasicConsumer(_channel);
    consumer.Received += async (_, eventArgs) =>
            {
                try
                {
                    await callback(eventArgs.Body.ToArray());
                }
                catch(JsonException aa)
                {
                    Console.WriteLine(nameof(Consume) +":" + aa.ToString());
                }
                catch (Exception ex)
                {
                    var data = System.Text.Encoding.Default.GetString((eventArgs.Body.ToArray()));
                    Serilog.Log.Logger.Error($"Rabbit Consumer exception :{ex.ToString()} with Data:{System.Text.Encoding.Default.GetString((eventArgs.Body.ToArray())) }");
                    Console.WriteLine(nameof(Consume) +":" + ex.ToString());
                }
                _channel.BasicAck(eventArgs.DeliveryTag, multiple: false);
            };

    _channel.BasicConsume(topic, autoAck: false, consumer);

    return Task.CompletedTask;
}
dbc
  • 104,963
  • 20
  • 228
  • 340
Ehsan Akbar
  • 6,977
  • 19
  • 96
  • 180
  • I cannot reproduce the error. It seems to work fine with your code: https://dotnetfiddle.net/w8oqdK. If you're actually trying to deserialize an array (and not the posted JSON example) you need to `JsonSerializer.Deserialize(Value)` – Xerillio Sep 04 '22 at 09:20
  • @Xerillio thank you for your comment yes I pass byte to the consumer .I updated my question – Ehsan Akbar Sep 04 '22 at 09:23
  • @Xerillio Would you please let me know if you check the consumer code ? – Ehsan Akbar Sep 04 '22 at 09:32
  • 1
    I don't think that part of the code changes so much. The important part is what `payload` contains. Try to convert the byte array to a string before passing it to `Deserialize` and see if that works. If it does you probably need to specify a different encoding. – Xerillio Sep 04 '22 at 10:13
  • Try `var rawData = JsonSerializer.Deserialize(System.Text.Encoding.Default.GetString(payload));` – Guru Stron Sep 04 '22 at 10:23
  • @Xerillio I found the problem .The problem is the this character " in the first and end of string ,another thing is the character \ .when I remove these character in string every thing works fine . – Ehsan Akbar Sep 04 '22 at 10:24
  • @GuruStron I found the problem .The problem is the this character " in the first and end of string ,another thing is the character \ .when I remove these character in string every thing works fine,But I don't know how can I remove these characters ? – Ehsan Akbar Sep 04 '22 at 10:27
  • 2
    The error message says a problem at column 599 - but your json is far less long than that. But your example of the JSON `"{\"info\":{\"request_id\":1...` would be 597 characters long, but it is not pure JSON - it is C# string literal containing JSON. Do you feed somehow an escaped JSON to deserialize instead of the pure JSON (that is only 529 bytes long)? – BitLauncher Sep 04 '22 at 12:05
  • @BitLauncher Yes you are right when I remove backslash and " from the string .it works fine .why ? – Ehsan Akbar Sep 04 '22 at 12:15
  • @BitLauncher Is there any better solution ?var stringPayload = System.Text.Encoding.Default.GetString((payload.ToArray())).Replace(@"\", ""); var stringChanged= stringPayload.Substring(1, stringPayload.Length - 2); – Ehsan Akbar Sep 04 '22 at 12:16
  • @Ehsan Akbar: I can only guess, that the one who sends the message, sends the message already wrongly with \" and surrounded by "_ Please check the payload variable content - or with other tools like postman, etherreal, ... – BitLauncher Sep 05 '22 at 19:09
  • Looks like the JSON was double-serialized by the sender. Thus usually happens when a server tries to return manually serialized JSON via `return alreadySerializedJsonString;` -- and the framework serializes it a second time. See e.g. [JSON.NET Parser *seems* to be double serializing my objects](https://stackoverflow.com/q/25559179/3744182), [Strings sent through Web API's gets wrapped in quotes](https://stackoverflow.com/q/33681978/3744182). The best solution is for the server to fix their code and not double-serialize the JSON. – dbc Sep 12 '22 at 20:54
  • If you cannot fix the sending code and **must** parse double-serialized JSON, you may do so with a `JsonConverter` such as the one from [How do I deserialize a nested JSON object which is a string in System.Text.Json?](https://stackoverflow.com/q/69506159). Or, since it is the root object that was double-serialized, do `JsonSerializer.Deserialize(JsonSerializer.Deserialize(payload));` – dbc Sep 12 '22 at 20:58
  • In fact this looks like a duplicate of [Strings sent through Web API's gets wrapped in quotes](https://stackoverflow.com/q/33681978/3744182) or [How do I deserialize a nested JSON object which is a string in System.Text.Json?](https://stackoverflow.com/q/69506159). Agree? – dbc Sep 12 '22 at 20:59
  • @T.S. - you edited the question to remove the double-serializing of the JSON, which was confirmed in [this comment](https://stackoverflow.com/questions/73598081/the-json-value-could-not-be-converted-to-model-in-net-core#comment129967155_73598081). I've rolled the change back. – dbc Sep 12 '22 at 21:31
  • @dbc I really don't understand what is the problem here because i took everything here into fiddle and it all worked `string dd ="{\"info\":{\"request_id\":148786,.....}"; var inst = JsonSerializer.Deserialize(dd); Console.WriteLine(inst.info.request_type);` I removed the quotes to format json as model instead of having it as c# string, so we can see better field matching. – T.S. Sep 12 '22 at 21:45
  • 1
    @T.S. - You are interpreting `"{\"info\":{\"request_id\":148786,.....}"` as a c# string literal with c# string literal escaping, but this is in fact the raw JSON not a c# string literal. JSON escaping happens to look like c# string literal escaping, but c# string literal escaping is resolved at compile time but JSON escaping is not. – dbc Sep 12 '22 at 21:53

0 Answers0