Как конвертировать JSON в курсор FoxPro - PullRequest
0 голосов
/ 31 октября 2019

Файл содержит список счетов в формате json, например:

{
    "status": "OK", "statusCode": 200, "messages": null,
    "data": [{
        "payment_type": "banktransfer", "fine": "0.200000", "quote_id": null, "order_id": null, "prepayment_id": null, "credited_invoices": [],
        "interested_party_address_id": 279, "project_id": 875, "currency": "EUR", "owner_id": 3, "date": "2019-03-15", "deadline": "2019-03-20",
    },

    {
        "payment_type": "banktransfer", "fine": "0.30000", "quote_id": null, "order_id": null, "prepayment_id": null, "credited_invoices": [],
        "interested_party_address_id": 79, "project_id": 85, "currency": "EUR", "owner_id": 3, "date": "2019-04-15", "deadline": "2019-43-20",
    }
    .... more same type elements
    ]
}

Как преобразовать его в курсор FoxPRo? Курсор должен содержать столбцы payment_type, fine, quote_id и т. Д.

Я пытался

https://archive.codeplex.com/?p=qdfoxjson

и

http://www.sweetpotatosoftware.com/blog/index.php/2008/12/19/visual-foxpro-json-class-update/

но похоже, что они требуют, чтобы json был в другом формате, чем мой json.

Andrus

Ответы [ 2 ]

1 голос
/ 31 октября 2019

Во-первых, ваш JSON недействителен. Не должно быть запятой после значений даты «крайнего срока».

Во-вторых, нет механизма, который бы сообщал VFP, как отображать элементы в поля. Так что вы должны сделать это сами.

Для этого я бы использовал библиотеку njJson , в частности nfJsonRead.

Предполагая, что ваш JSON находится в файле 'test. json 'и у вас есть nfJsonRead.prg, например:

    Close All
    Clear All
    Clear

    Set Procedure To nfJsonRead additive

    * -- Add the other fields as appropriate.
    Create Cursor mydata (payment_type c(20), fine n(12, 2))

    loJson = nfjsonread(FileToStr("test.json"))

    For each loData in loJson.data

        Insert into mydata values (loData.payment_type, Val(loData.fine))

    EndFor
0 голосов
/ 31 октября 2019

Просто быстрое, что я придумал для тебя. Если бы у меня было больше материала в аналогичном формате, я бы сделал некоторую структуру курсора / таблицы: «поиск начального разделителя», «поиск конечного разделителя», «конечный тип данных» и т. Д., А затем цикл для каждой части. Здесь я на самом деле показываю, как извлекается каждая часть и как получить по одной строке данных за раз.

** Example to put into a string called "json", no other context to json
TEXT TO json noshow
{
    "status": "OK", "statusCode": 200, "messages": null,
    "data": [{1
        "payment_type": "banktransfer", "fine": "0.200000", "quote_id": null, "order_id": null, "prepayment_id": null, "credited_invoices": [],
        "interested_party_address_id": 279, "project_id": 875, "currency": "EUR", "owner_id": 3, "date": "2019-03-15", "deadline": "2019-03-20",
    },

    {2
        "payment_type": "banktransfer", "fine": "0.30000", "quote_id": null, "order_id": null, "prepayment_id": null, "credited_invoices": [],
        "interested_party_address_id": 79, "project_id": 85, "currency": "EUR", "owner_id": 3, "date": "2019-04-15", "deadline": "2019-43-20",
    }
    .... more same type elements
    ]
}
ENDTEXT

** Strip the "Status" component ang get just the Data
json = SUBSTR( json, ATC( ["data":], json ))



CREATE CURSOR C_ImportRecs;
(   PayType c(20),;
    Fine    n(10,6),;
    QuoteID i,;
    OrderID i,;
    PrepayID i,;
    Invoices c(20),;
    IntPartyAddrID i,;
    ProjectID i,;
    TransCurrency c(3),;
    OwnerID i,;
    DatePart c(15),;
    TransDate d,;
    DeadPart c(15),;
    Deadline d )

** scatter all fields to an object which will have fields by same name  
SCATTER NAME newRec

** start counter to 1
nRow = 1
DO while .t.
    ** Look within the json string for the "nRow" instance of data starting / ending with { / }
    oneData = STREXTRACT( json, "{", "}", nRow )

    ** if no more entries, get out   
    IF EMPTY( ALLTRIM( oneData ))
        exit
    ENDIF 


    ** if memory variables are same name as cursor/table columns, simplifies insert
    newRec.PayType = STREXTRACT( oneData, ["payment_type": "], ["] )
    newRec.Fine = VAL( STREXTRACT( oneData, ["fine": "], ["] ))

    ** not including closing quote as ending delimiter since null allowed, looking for the "," after the IDs
    newRec.QuoteID = INT( VAL( STREXTRACT( oneData, ["quote_id": ], [,] ) ))
    newRec.OrderID = INT( VAL( STREXTRACT( oneData, ["order_id": ], [,] ) ))
    newRec.PrepayID = INT( VAL( STREXTRACT( oneData, ["prepayment_id": ], [,] ) ))

    newRec.Invoices = STREXTRACT( oneData, ["credited_invoices": ], [,] )

    newRec.IntPartyAddrID = INT( VAL( STREXTRACT( oneData, ["interested_party_address_id": ], [,] ) ))
    newRec.ProjectID = INT( VAL( STREXTRACT( oneData, ["project_id": ], [,] ) ))

    ** Currency is reserved word.
    newRec.TransCurrency = STREXTRACT( oneData, ["currency": "], ["] )

    newRec.OwnerID = INT( VAL( STREXTRACT( oneData, ["owner_id": ], [,] ) ))

    ** Date is reserved word
    newRec.DatePart = ""
    newRec.DatePart = STREXTRACT( oneData, ["date": "], ["] )

    ** Nice for macro substitution.  Take incoming date format of ex: "2019-03-15"
    ** and change to "2019,03,15"  This is because the DATE() function expects 
    ** 3 parameters for YEAR, MONTH, DAY
    tryDate = STRTRAN( newRec.DatePart, "-", "," )
    ** Now, by using macro via "&" forces the line below to immediately run as if
    ** run as if it was DATE( 2019,03,15) and create an actual date value
    TRY
        newRec.TransDate = DATE( &tryDate )
    CATCH
        newRec.TransDate = CTOD( "" )
    ENDTRY 

    ** same for deadline
    newRec.DeadPart = STREXTRACT( oneData, ["deadline": "], ["] )
    tryDate = STRTRAN( newRec.DeadPart, "-", "," )
    TRY
        ** your second record has a month 43 which is an invalid month
        newRec.Deadline = DATE( &tryDate )
    CATCH
        newRec.Deadline = CTOD( "" )
    ENDTRY 


    ** Since the cursor "C_ImportRecs" is already the active focus, 
    ** we can just insert from memory variables
    INSERT INTO C_ImportRecs FROM NAME newRec

    ** try if any more records
    nRow = nRow + 1
ENDDO


BROWSE NORMAL NOCAPTIONS NOWAIT 
...