Export to JSONL

This commit is contained in:
Francesco 2023-10-20 12:42:25 +02:00
parent 355d98bd41
commit 6f9f567f6e
3 changed files with 95 additions and 1 deletions

View File

@ -6,6 +6,7 @@ import java.io.StringWriter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -31,6 +32,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import tech.ailef.dbadmin.external.DbAdmin; import tech.ailef.dbadmin.external.DbAdmin;
import tech.ailef.dbadmin.external.dbmapping.DbAdminRepository; import tech.ailef.dbadmin.external.dbmapping.DbAdminRepository;
import tech.ailef.dbadmin.external.dbmapping.DbField; import tech.ailef.dbadmin.external.dbmapping.DbField;
@ -53,6 +57,9 @@ public class DataExportController {
@Autowired @Autowired
private DbAdminRepository repository; private DbAdminRepository repository;
@Autowired
private ObjectMapper mapper;
@GetMapping("/{className}") @GetMapping("/{className}")
@ResponseBody @ResponseBody
public ResponseEntity<byte[]> export(@PathVariable String className, @RequestParam(required = false) String query, public ResponseEntity<byte[]> export(@PathVariable String className, @RequestParam(required = false) String query,
@ -90,6 +97,12 @@ public class DataExportController {
.header(HttpHeaders.CONTENT_DISPOSITION, .header(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"export_" + schema.getJavaClass().getSimpleName() + ".xlsx\"") "attachment; filename=\"export_" + schema.getJavaClass().getSimpleName() + ".xlsx\"")
.body(toXlsx(sheetName, results, fieldsToInclude, raw)); .body(toXlsx(sheetName, results, fieldsToInclude, raw));
case JSONL:
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"export_" + schema.getJavaClass().getSimpleName() + ".jsonl\"")
.body(toJsonl(results, fieldsToInclude, raw).getBytes());
default: default:
throw new DbAdminException("Invalid DataExportFormat"); throw new DbAdminException("Invalid DataExportFormat");
} }
@ -139,6 +152,35 @@ public class DataExportController {
return fos.toByteArray(); return fos.toByteArray();
} }
/**
* Converts a list of DbObjects to a string containing their JSONL representation.
* One item per line in JSON format.
* @param items the items to be serialized
* @param fields the fields to take from each item
* @param raw whether to use raw values or not
* @return a string containing the items serialized in JSONL format
*/
private String toJsonl(List<DbObject> items, List<String> fields, boolean raw) {
if (items.isEmpty())
return "";
StringBuilder sb = new StringBuilder();
for (DbObject item : items) {
Map<String, Object> map = item.toMap(fields, raw);
try {
String json = mapper.writeValueAsString(map);
sb.append(json);
} catch (JsonProcessingException e) {
throw new DbAdminException(e);
}
sb.append("\n");
}
return sb.toString();
}
private String toCsv(List<DbObject> items, List<String> fields, boolean raw) { private String toCsv(List<DbObject> items, List<String> fields, boolean raw) {
if (items.isEmpty()) if (items.isEmpty())
return ""; return "";
@ -219,4 +261,5 @@ public class DataExportController {
return record; return record;
} }
} }

View File

@ -22,7 +22,9 @@ package tech.ailef.dbadmin.external.dbmapping;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -256,6 +258,54 @@ public class DbObject {
return null; return null;
} }
/**
* Converts this object to map where each key is a field name,
* including only the specified fields.
* If raw, values are not processed and are included as they are
* in the database table.
*
* @return
*/
public Map<String, Object> toMap(List<String> fields, boolean raw) {
Map<String, Object> result = new HashMap<>();
for (String field : fields) {
DbField dbField = schema.getFieldByName(field);
if (dbField == null) {
// The field is a computed column
Object computedValue = compute(field);
result.put(field, computedValue);
} else {
if (dbField.isForeignKey()) {
DbObject linkedItem = traverse(dbField);
if (linkedItem == null) result.put(field, null);
else {
if (raw) {
result.put(field, linkedItem.getPrimaryKeyValue().toString());
} else {
result.put(field, linkedItem.getPrimaryKeyValue() + " (" + linkedItem.getDisplayName() + ")");
}
}
} else {
if (raw) {
DbFieldValue fieldValue = get(dbField);
if (fieldValue.getValue() == null) result.put(field, null);
else result.put(field, fieldValue.getValue().toString());
} else {
result.put(field, get(dbField).getFormattedValue());
}
}
}
}
return result;
}
@Override @Override
public String toString() { public String toString() {
return "DbObject [instance=" + instance + ", schema=" + schema + "]"; return "DbObject [instance=" + instance + ", schema=" + schema + "]";

View File

@ -2,5 +2,6 @@ package tech.ailef.dbadmin.external.dto;
public enum DataExportFormat { public enum DataExportFormat {
CSV, CSV,
XLSX; XLSX,
JSONL;
} }