The JSON value could not be converted to System.Boolean

Permalänk
Medlem

The JSON value could not be converted to System.Boolean

Hej allesammans!

Jag sitter med en liten simpel webbapplikation där jag har problem med att posta ett nytt objekt till min databas.
Ett av målen med projektet är att se hur långt man kan komma med så simpel "teknik" som möjligt, så frontenden är skriven i HTML, CSS och JS/AJAX. Backenden är ett webapi i C# som går mot MongoDb Atlas.
Jag har inte kodat mycket alls i JS, så jag har sökt massvis men inte lyckats få det att funka.

Att skapa ett nytt objekt, i detta fall en motorcykel, går bra tills dess att jag lägger in en boolean, isActive. Tar jag bort den ur formuläret skapas motorcykeln med isActive = false per standard.

HTML-formuläret (kraftigt nedkortad för läsbarhet):

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> </head> <body> <form id="createForm" method="post" enctype="application/json"></form> <table id="createVehicleTable"> <tr> <td> <label for="isActive">For sale:</label><br /> <input type="radio" id="yes" name="isActive" value="yes" form="createForm" /> <label for="yes">Yes</label><br /> <input type="radio" id="no" name="isActive" value="no" form="createForm" /> <label for="no">No</label><br /> </td> </tr> <tr> <td> <input type="submit" value="Create Vehicle" form="createForm" /> </td> </tr> </table> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min..."></script> <script src="./scripts/api-post-new.js" language="JavaScript" type="text/javascript" ></script> </body> </html>

Javascriptet:

const api_url = "http://mittFinaApi/api/motorcycles/create"; const serialize_form = (form) => JSON.stringify( Array.from(new FormData(form).entries()).reduce( (m, [key, value]) => Object.assign(m, { [key]: value }), {} ) ); $("#createForm").on("submit", function (event) { event.preventDefault(); const json = serialize_form(this); console.log(json); $.ajax({ type: "POST", url: api_url, data: json, contentType: "application/json", success: function (result) { console.log(result); document.getElementById("createForm").reset(); alert("Vehicle saved successfully."); }, error: function (result, status) { console.log(result); alert("Something went wrong when saving vehicle."); }, }); });

Felmeddelandet jag får är: The JSON value could not be converted to System.Boolean. Path: $.isActive | LineNumber: 0 | BytePositionInLine: 2 och kikar man i console så ser man att det är en string = "true".

Backend ser ut såhär:
Endpoint:

[HttpPost, Route("create")] [ProducesResponseType(typeof(int), 200)] public async Task<IActionResult> Post([FromBody] Motorcycles newMotorcycles) { if (!ModelState.IsValid) { return BadRequest(ModelState); } await _motorcyclesService.CreateAsync(newMotorcycles); return CreatedAtAction(nameof(GetAll), new { id = newMotorcycles.Id }, newMotorcycles); }

Service:

public async Task CreateAsync(Motorcycles newMotorcycle) => await _motorcycleCollection.InsertOneAsync(newMotorcycle);

Jag har lagt ungefär 10h på att lösa detta, så nu vänder jag mig hit för hjälp och råd.

Hur löser jag mitt problem?
Är min function för komplex?
Vad kan göras bättre?

Tacksam för all hjälp.

Visa signatur

» AMD Ryzen 5 2600X » 16 Gb DDR4 » ASUS GTX 1060 6 Gb OC » 1 Tb M.2 PCIe NVME

Vänligen citera om du pratar med mig

Permalänk
Medlem

Antingen måste du skicka isActive som "isActive":true, eller så måste du konvertera från en sträng med "bool.Parse(str)". För att det senare ska funka måste du säkert sätta upp en custom converter på något sätt. Det är svårt att säga mer när man inte har hela projektet och ser vilka libraries det bygger på.

Visa signatur

Bra, snabbt, billigt; välj två.

Ljud
PC → ODAC/O2 → Sennheiser HD650/Ultrasone PRO 900/...
PC → S.M.S.L SA300 → Bowers & Wilkins 607

Permalänk
Medlem

Svårt att veta när man inte ser hela koden, plus att jag inte kodar i de här språken.
Men kan du inte ändra datatypen till boolean. Eller skriva nån hjälpmetod som konverterar en sträng till en boolean innan du sparar den i db.

Edit: Tvåa på bollen

Permalänk
Medlem

Radio buttons verkar bara kunna generera string values, inte boolean, så konvertera den till boolean någonstans i ditt script kanske?

Ej exakt lösningsexempel nedan, men ett förslag:

if(isset($_POST['SubmitButton'])) { $_POST['IsActive'] = $_POST['IsActive'] == 'true' ? true : false; }

Permalänk
Medlem

”isActive”:”true”

Betyder alltså att det är ett strängvärde, strängen ”true”

Du kan göra not equals på den istället för !-operatorn du använder

Permalänk
Medlem

Som Phod säger så ska en boolean vara utan citationstecken i en json-fil och det är därför du får ett errormess i din backend. Så, som han också skriver, antingen ser du till att skicka i rätt format från frontend eller så tar du emot som en string och parsar till en bool. Det finns iofs en lösning till och det är att du ändrar din property i backend till att vara en string och hantera det som en string istället.

Permalänk
Medlem
Skrivet av Phod:

Antingen måste du skicka isActive som "isActive":true, eller så måste du konvertera från en sträng med "bool.Parse(str)". För att det senare ska funka måste du säkert sätta upp en custom converter på något sätt. Det är svårt att säga mer när man inte har hela projektet och ser vilka libraries det bygger på.

Skrivet av prod01:

Svårt att veta när man inte ser hela koden, plus att jag inte kodar i de här språken.
Men kan du inte ändra datatypen till boolean. Eller skriva nån hjälpmetod som konverterar en sträng till en boolean innan du sparar den i db.

Edit: Tvåa på bollen

Skrivet av jonkul:

Radio buttons verkar bara kunna generera string values, inte boolean, så konvertera den till boolean någonstans i ditt script kanske?

Ej exakt lösningsexempel nedan, men ett förslag:

if(isset($_POST['SubmitButton'])) { $_POST['IsActive'] = $_POST['IsActive'] == 'true' ? true : false; }

Skrivet av medbor:

”isActive”:”true”

Betyder alltså att det är ett strängvärde, strängen ”true”

Du kan göra not equals på den istället för !-operatorn du använder

Skrivet av Wilworin:

Som Phod säger så ska en boolean vara utan citationstecken i en json-fil och det är därför du får ett errormess i din backend. Så, som han också skriver, antingen ser du till att skicka i rätt format från frontend eller så tar du emot som en string och parsar till en bool. Det finns iofs en lösning till och det är att du ändrar din property i backend till att vara en string och hantera det som en string istället.

Ja, precis. Den blir en sträng (JSON.Stringify()) och därför accepterar den inte bool. Men typen int går fint av någon anledning.
Har testat skriva (läs: kopierat) en custom bool converter, men problemet kvarstår.

Sett flera som föreslår en lösning likt den @jonkul använder, men har inte lyckats med det heller.

Andra säger att jag bara ska installera Newtonsoft.Json istället för att använda Microsofts egna System.Text.Json, men så enkelt var det inte heller. (Den Custom converter jag lade in använder sig av Newtonsoft.Json).

Funderar på att ändra datatypen till sträng sålänge som Wilworin föreslog så jag kommer vidare med projektet så får det bli en senare nöt att knäcka. Har ett par endpoints att ändra också isf, då de i nuläget går på bool i sitt anrop.

Detta problem känns om en sån där busenkel grej där lösningen är mitt framför ögonen på mig.

Hojta gärna om ni kommer på något. Jag är verkligen tacksam!

Visa signatur

» AMD Ryzen 5 2600X » 16 Gb DDR4 » ASUS GTX 1060 6 Gb OC » 1 Tb M.2 PCIe NVME

Vänligen citera om du pratar med mig

Permalänk
Medlem

The JSON value could not be converted to System.Boolean betyder att du måste konvertera strängen till en boolean altså i detta fallet True.

Nu kan jag bara Python men tror inte du kan använda dig utav JSON.stringify

Visa signatur

AMD 7800X3D | ASUS TUF X670E-PLUS | Corsair Vengeance DDR5 32GB EXPO | ASUS TUF 4090 OC 24GB |
Noctua NH-U12A | Corsair 4000D | Corsair AX1200W | Steelseries Apex 7 | Steelseries Sensei Ten | ASUS VG35VQ

https://github.com/Mariusz89B

Permalänk
Medlem
Skrivet av Bebben:

Ja, precis. Den blir en sträng (JSON.Stringify()) och därför accepterar den inte bool. Men typen int går fint av någon anledning.
Har testat skriva (läs: kopierat) en custom bool converter, men problemet kvarstår.

Sett flera som föreslår en lösning likt den @jonkul använder, men har inte lyckats med det heller.

Andra säger att jag bara ska installera Newtonsoft.Json istället för att använda Microsofts egna System.Text.Json, men så enkelt var det inte heller. (Den Custom converter jag lade in använder sig av Newtonsoft.Json).

Funderar på att ändra datatypen till sträng sålänge som Wilworin föreslog så jag kommer vidare med projektet så får det bli en senare nöt att knäcka. Har ett par endpoints att ändra också isf, då de i nuläget går på bool i sitt anrop.

Detta problem känns om en sån där busenkel grej där lösningen är mitt framför ögonen på mig.

Hojta gärna om ni kommer på något. Jag är verkligen tacksam!

Du borde kunna göra:
if(!”true”.equals(ModelState.IsValid))
eller såklart
if(”false”.equals(ModelState.IsValid))

Dvs jämföra strängar

Permalänk

Hur känslig är json på små/stora bokstäver?
I koden letar man efter IsActive medans i json står det isActive. Om den är känslig på det, så borde det betyda att IsActive är tom och det blir inte önskvärt resultat utav det.

Permalänk
Medlem

Är det alltså din C#-backend som smäller? Då låter det som att du antingen behöver se till att din frontend konverterar string-versionen av din bool till en faktisk bool eller hanterar det vid mottagandet i backend. Eftersom frontenden sannolikt kan skicka in alla möjliga datatyper i roliga sträng-format känns det spontant enklast att hantera detta i backend. Du kan även resonera som så att din backend skulle kunna serva flera olika fronends och då är det enklare att backended styr upp formateringen än att kräva att varje klient ska lösa det.

Det ser ganska simpelt ut i C# med Newtonsoft. Här finns någon som skrivet en custom converter för olika typer av sträng-versioner av bool-värden: https://gist.github.com/randyburden/5924981. Och här är exempel på hur du använder en Custom Converter: https://www.newtonsoft.com/json/help/html/CustomJsonConverter....

Permalänk
Medlem

Du ska inte använda JSON.stringify(), skicka ditt svar som ren JSON och låt klienten sköta konverteringen.

Om din klass är korrekt implementerad så ska det gå bra.

Exempel:

[JsonPropertyName("name")] public string Name { get; set; }

Visa signatur

AMD Ryzen 7 1700X 3.8 GHz 20MB | ASUS PRIME X370-PRO | MSI GeForce GTX 1080 Gaming X 8GB | G.Skill 16GB DDR4 3200 MHz CL14 Flare X | Corsair RM650x 650W

Permalänk
Medlem

God morgon! Jag löste problemet inatt efter att jag skrev sista inlägget.

Kommer posta lösningen när jag kommer hem ikväll.

Återigen, tacksam för hjälpen och råden.

Visa signatur

» AMD Ryzen 5 2600X » 16 Gb DDR4 » ASUS GTX 1060 6 Gb OC » 1 Tb M.2 PCIe NVME

Vänligen citera om du pratar med mig

Permalänk
Medlem

Jo, så jag löste det med att använda denna AJAX-funktionen istället för den jag postade tidigare:

$("#btn").click(function () { $.post( api_url, $("#createForm").serialize(), function (json) { console.log(json); document.getElementById("createForm").reset(); alert("Vehicle saved successfully."); }, "json" ); });

Kort och smidigt.

Jag installerade även NewtonsoftJson i min backend, men har inte behövt implementera den någonstans så jag tror bara att min function som använde stringify() ställde till det.
Kikar jag i consol nu så skrivs det ut ett korrekt objekt snarare än en lång sträng som innan.

Var dag är en ny lärdom.

Visa signatur

» AMD Ryzen 5 2600X » 16 Gb DDR4 » ASUS GTX 1060 6 Gb OC » 1 Tb M.2 PCIe NVME

Vänligen citera om du pratar med mig

Permalänk
Medlem
Skrivet av Bebben:

Jo, så jag löste det med att använda denna AJAX-funktionen istället för den jag postade tidigare:

$("#btn").click(function () { $.post( api_url, $("#createForm").serialize(), function (json) { console.log(json); document.getElementById("createForm").reset(); alert("Vehicle saved successfully."); }, "json" ); });

Kort och smidigt.

Jag installerade även NewtonsoftJson i min backend, men har inte behövt implementera den någonstans så jag tror bara att min function som använde stringify() ställde till det.
Kikar jag i consol nu så skrivs det ut ett korrekt objekt snarare än en lång sträng som innan.

Var dag är en ny lärdom.

Du behöver inte Newtonsoft.Json. Det är "legacy"-alternativet, numera har Microsoft gjort en egen implementation av ett JSON-framework, System.Text.Json. Du använder redan det senare.

Newtonsoft.Json är har mer features, System.Text.Json är snabbare. För nya projekt är det lika bra att köra på System.Text.Json, om man inte vet med sig att man behöver features i Newtonsoft.Json.

Visa signatur

Bra, snabbt, billigt; välj två.

Ljud
PC → ODAC/O2 → Sennheiser HD650/Ultrasone PRO 900/...
PC → S.M.S.L SA300 → Bowers & Wilkins 607