Buenas, copia el siguiente código en un prg y pruebalo, quien sabe cumple con lo que necesitas nos comentas
FUNCTION cursortostr
PARAMETERS cAliasCursor, nAccion, cToStr, ltofile, cNameFile
*/cAliasCursor Nombre del cursor a obtener o pasar los datos
*/nAccion 1 pasar de tabla a cadena
*/ 2 de cadena a tabla cierra cursor si existe y lo crea con la estructura
*/ 3 si existe cursor no lo cierra y pasa los datos
*/cToStr Cadena con los datos a pasar al cursor
*/ltofile Si es verdadero y la opcion 1 lo graba en un archivo los datos del cursor
*/ si la opcion es 2 o 3 lee los datos desde un archivo y lo carga al cursor
*/cNameFile Nombre del archivo a grabar o a leer segun nAccion
*/se va ha crear una estructura
*/ primer item la definicion de la tabla y las demas los datos de la tabla
*/ "{campo1,n,(10,2),|campo2,c,(30),|campo3, l,,|campo4,D,,|};{"campo1":8.30,"campo2" : "datos de texto","campo3" :.t.,"campo4" : 01/01/2021,};"
LOCAL lCrearTabla, cPalote, nICampos, cCampoAdd, cCampo, cTipo, cWidth, cDecimal,;
cToString, nIField, cFila, nItems, oFila, cAliasActual
IF VARTYPE(cNameFile)="L"
cNameFile="cursortostr.txt"
ENDIF
cAliasActual=ALIAS()
lCrearTabla=.f.
IF EMPTY(cAliasCursor)
RETURN -1
ENDIF
IF !USED(cAliasCursor) AND nAccion=1
RETURN -1
ELSE
IF nAccion=2 AND !USED(cAliasCursor)
lCrearTabla=.t.
ENDIF
ENDIF
IF nAccion=1 &&leer la tabla
*/obtenemos los campos de la tabla
cPalote="|"
nICampos=AFIELDS(aTabla,cAliasCursor)
cCampoAdd=""
FOR nIfield=1 TO nICampos
cCampo=ALLTRIM(aTabla[nIField,1])
cTipo=ALLTRIM(aTabla[nIField,2])
cWidth=ALLTRIM(STR(aTabla[nIField,3],3,0))
cDecimal=ALLTRIM(STR(aTabla[nIField,4],3,0))
cIsNull=TRANSFORM(aTabla[nIField,5])
cCampoAdd=cCampoAdd+cCampo+","+cTipo+","+cWidth+","+cDecimal+","+cIsNull+","+cPalote
ENDFOR
*SET STEP ON
cCampoAdd="{"+cCampoAdd+"};"
cFilasAdd=""
oField=.null.
*/ahora vamos a cargar los datos
SELECT (cAliasCursor)
SCAN
Scatter Memo Name oField
*/lo pasamos a json
ctxt=json.stringify(oField)
cCampoAdd=cCampoAdd+cTxt+";"
ENDSCAN
IF ltofile
nretorno=STRTOFILE(cCampoAdd,cNameFile)
ENDIF
RETURN cCampoAdd
ELSE
IF nAccion=2 OR nAccion=3 &&crear si no existe y llenar la tabla con los datos almancenados
*/recuperar la cabecera con los datos del cursor
IF ltofile
cToStr=FILETOSTR(cNameFile)
ENDIF
cCabecera=comboitems(cToStr,1)
nICampos=comboitems(cCabecera,-1,"|")
*/ahora lo pasamos a un array como el array original de la tabla
DIMENSION aTabla[nICampos,18]
FOR nIField=1 TO nICampos
cField=comboitems(cCabecera,nIField,"|")
cField=STRTRAN(cField,"{","")
aTabla[nIField,1]=comboitems(cField,1,",")
aTabla[nIField,2]=ALLTRIM(comboitems(cField,2,","))
aTabla[nIField,3]=INT(VAL(comboitems(cField,3,",")))
aTabla[nIField,4]=INT(VAL(comboitems(cField,4,",")))
aTabla[nIField,5]=(".T."=comboitems(cField,5,","))
aTabla[nIField,6]=.f.
aTabla[nIField,7]=""
aTabla[nIField,8]=""
aTabla[nIField,9]=""
aTabla[nIField,10]=""
aTabla[nIField,11]=""
aTabla[nIField,12]=""
aTabla[nIField,13]=""
aTabla[nIField,14]=""
aTabla[nIField,15]=""
aTabla[nIField,16]=""
aTabla[nIField,17]=0
aTabla[nIField,18]=0
ENDFOR
*/preguntamos si exise el cursor
IF nAccion=2 AND USED(cAliasCursor) &&lo cerramos y lo volvemos a crear
SELECT (cAliasCursor)
USE
ENDIF
IF !USED(cAliasCursor)
CREATE CURSOR (cAliasCursor) from ARRAY aTabla
ENDIF
*/ahora si llenar sus datos
nItems=comboitems(cToStr,-1,"};")-1
IF nItems>0
FOR nIFilas=1 TO nItems
cFila=comboitems(cToStr,nIfilas+1,"};")
cFila=SUBSTR(cFila,2)+"}"
*/ahora lo pasamos a un objeto
oFila=json.parse(cFila)
INSERT INTO (cAliasCursor) FROM NAME oFila
ENDFOR
ENDIF
ENDIF
ENDIF
IF !EMPTY(cAliasActual)
SELECT (cAliasActual)
ENDIF