Closed williamoanta closed 2 years ago
The computed field shouldn't have a dedicated jreq
becuase by adding jreq "Age"
you are effectively requiring that field in the json (therefore the combinator name) and it's my understanding that's not what you want.
Simply remove the whole line:
// <*> jreq "Age" (Some << fun x -> getAge x.DateOfBirth)
and remove the unused parameter ag
, already hinted by the compiler.
Your code should look like this:
#r "nuget: Fleece.NewtonsoftJson"
open System
open Fleece.Newtonsoft
open Fleece.Newtonsoft.Operators
type UserId = int
type SexMeasure = bool
type AgeMeasure = int
type BiometricMeasure = float
type UTCTick = DateTime
type RoadmapStatus = string
type QuestionStore = string
type MedicalConditions = string
type ScoreStore = int
type MedicalConditionStore = int
type RejectedMedicalConditions = bool
type RejectedMedicalConditionStore = string
type Biometrics = string
type BiometricStore = string
let getAge (x: DateTime) = int ((DateTime.Now - x).TotalDays / 365.25)
type User = {
Id: UserId
DateOfBirth: DateTime
Country: string
State: string
SexAtBirth: SexMeasure
EthnicBackground: string
Education: string
Occupation: string
Nationality: string
SexualOrientation: string
RelationshipStatus: string
Children: int
Phone: int
Email: string
RegistrationCompleted: bool
Age: AgeMeasure
Weight: BiometricMeasure
Height: BiometricMeasure
LastMod: UTCTick
RoadmapStatus: RoadmapStatus
LastProcessedGuidelineId: int
QuestionsStore: QuestionStore list
MedicalConditions: MedicalConditionStore list
RejectedMedicalConditions: RejectedMedicalConditionStore list
Scores: ScoreStore list
Biometrics: BiometricStore list
} with
static member JsonObjCodec =
(fun id db co st se eb educ occup nat sexo rels chi pho ema regc we he lm rs lid qs mc rmc sc bi ->
{Id = id; DateOfBirth = db; Country = co; State = st; SexAtBirth = se; EthnicBackground = eb;
Education = educ; Occupation = occup; Nationality = nat; SexualOrientation = sexo;
RelationshipStatus = rels; Children = chi; Phone = pho; Email = ema
RegistrationCompleted = regc; Age = getAge(db); Weight = we; Height = he;
LastMod = lm; RoadmapStatus = rs; LastProcessedGuidelineId = lid; QuestionsStore = qs;
MedicalConditions = mc; RejectedMedicalConditions = rmc; Scores = sc; Biometrics = bi })
<!> jreq "Id" (Some << fun x -> x.Id)
<*> jreq "DateOfBirth" (Some << fun x -> x.DateOfBirth)
<*> jreq "Country" (Some << fun x -> x.Country)
<*> jreq "State" (Some << fun x -> x.State)
<*> jreq "SexAtBirth" (Some << fun x -> x.SexAtBirth)
<*> jreq "EthnicBackground" (Some << fun x -> x.EthnicBackground)
<*> jreq "Education" (Some << fun x -> x.Education)
<*> jreq "Occupation" (Some << fun x -> x.Occupation)
<*> jreq "Nationality" (Some << fun x -> x.Nationality)
<*> jreq "SexualOrientation" (Some << fun x -> x.SexualOrientation)
<*> jreq "RelationshipStatus" (Some << fun x -> x.RelationshipStatus)
<*> jreq "Children" (Some << fun x -> x.Children)
<*> jreq "Phone" (Some << fun x -> x.Phone)
<*> jreq "Email" (Some << fun x -> x.Email)
<*> jreq "RegistrationCompleted" (Some << fun x -> x.RegistrationCompleted)
// <*> jreq "Age" (Some << fun x -> getAge x.DateOfBirth)
<*> jreq "Weight" (Some << fun x -> x.Weight)
<*> jreq "Height" (Some << fun x -> x.Height)
<*> jreq "LastMod" (Some << fun x -> x.LastMod)
<*> jreq "RoadmapStatus" (Some << fun x -> x.RoadmapStatus)
<*> jreq "LastProcessedGuidelineId" (Some << fun x -> x.LastProcessedGuidelineId)
<*> jreq "QuestionsStore" (Some << fun x -> x.QuestionsStore)
<*> jreq "MedicalConditions" (Some << fun x -> x.MedicalConditions)
<*> jreq "RejectedMedicalConditions" (Some << fun x -> x.RejectedMedicalConditions)
<*> jreq "Scores" (Some << fun x -> x.Scores)
<*> jreq "Biometrics" (Some << fun x -> x.Biometrics)
Please let me know if that solves your issue.
Note that I added some predefined values and #r directives to make your code compilable and I encourage to do so when writing repros to make them easy to reproduce for the person who's reading your code and that will surely increase chances to get help.
Thank you for your answer and advice.
This almost solves my problem, except that, although I am OK with not having the field when I do 'fromJSON' - because I am computing it from birth, I would still like to have the field present when I do 'toJSON', which does not happen with your proposed changes, as the field is not preset in the JSON representation when I do 'toJSON'.
Any ideas on how to narrow the solution to my case? Thank you!
p.s. To give more context, the reason I need this is because I would like the backend always to compute age based on birth - that is why I do not need it as part of the 'fromJSON'. But I would like to send the Age as part of the JSON sent by the backend to the frontend.
In that case take your original code and just change the Age fields's jreq
to jopt
.
@williamoanta does the above answer your question? If so could you please close the issue? Otherwise let me know. Thanks !
Assuming solved. Otherwise feel free to re-open.
I have the following type with JsonObjCodec defined:
I would like to compute "Age" based on "DateOfBirth":
<*> jreq "Age" (Some << fun x -> getAge x.DateOfBirth)
That means that the front-end should be able to send a JSON payload without "Age" in it, as age will always be computed on the backend based on "DateOfBirth". But this does not work, as when I send a JSON without "Age", I get the error that there is no match for "Age":
Any ideas on how to achieve my goal? Thanks!