You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					211 lines
				
				6.0 KiB
			
		
		
			
		
	
	
					211 lines
				
				6.0 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								import { Converter } from "./Converter";
							 | 
						||
| 
								 | 
							
								import CSVError from "./CSVError";
							 | 
						||
| 
								 | 
							
								import { CellParser, ColumnParam } from "./Parameters";
							 | 
						||
| 
								 | 
							
								import set from "lodash/set";
							 | 
						||
| 
								 | 
							
								import { ParseRuntime } from "./ParseRuntime";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var numReg = /^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$/;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								export default function (csvRows: string[][], conv: Converter): JSONResult[] {
							 | 
						||
| 
								 | 
							
								  const res: JSONResult[] = [];
							 | 
						||
| 
								 | 
							
								  for (let i = 0, len = csvRows.length; i < len; i++) {
							 | 
						||
| 
								 | 
							
								    const r = processRow(csvRows[i], conv, i);
							 | 
						||
| 
								 | 
							
								    if (r) {
							 | 
						||
| 
								 | 
							
								      res.push(r);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return res;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								export type JSONResult = {
							 | 
						||
| 
								 | 
							
								  [key: string]: any
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function processRow(row: string[], conv: Converter, index): JSONResult | null {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (conv.parseParam.checkColumn && conv.parseRuntime.headers && row.length !== conv.parseRuntime.headers.length) {
							 | 
						||
| 
								 | 
							
								    throw (CSVError.column_mismatched(conv.parseRuntime.parsedLineNumber + index))
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const headRow = conv.parseRuntime.headers || [];
							 | 
						||
| 
								 | 
							
								  const resultRow = convertRowToJson(row, headRow, conv);
							 | 
						||
| 
								 | 
							
								  if (resultRow) {
							 | 
						||
| 
								 | 
							
								    return resultRow;
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    return null;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function convertRowToJson(row: string[], headRow: string[], conv: Converter): { [key: string]: any } | null {
							 | 
						||
| 
								 | 
							
								  let hasValue = false;
							 | 
						||
| 
								 | 
							
								  const resultRow = {};
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								  for (let i = 0, len = row.length; i < len; i++) {
							 | 
						||
| 
								 | 
							
								    let item = row[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (conv.parseParam.ignoreEmpty && item === '') {
							 | 
						||
| 
								 | 
							
								      continue;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    hasValue = true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let head = headRow[i];
							 | 
						||
| 
								 | 
							
								    if (!head || head === "") {
							 | 
						||
| 
								 | 
							
								      head = headRow[i] = "field" + (i + 1);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    const convFunc = getConvFunc(head, i, conv);
							 | 
						||
| 
								 | 
							
								    if (convFunc) {
							 | 
						||
| 
								 | 
							
								      const convRes = convFunc(item, head, resultRow, row, i);
							 | 
						||
| 
								 | 
							
								      if (convRes !== undefined) {
							 | 
						||
| 
								 | 
							
								        setPath(resultRow, head, convRes, conv,i);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      // var flag = getFlag(head, i, param);
							 | 
						||
| 
								 | 
							
								      // if (flag === 'omit') {
							 | 
						||
| 
								 | 
							
								      //   continue;
							 | 
						||
| 
								 | 
							
								      // }
							 | 
						||
| 
								 | 
							
								      if (conv.parseParam.checkType) {
							 | 
						||
| 
								 | 
							
								        const convertFunc = checkType(item, head, i, conv);
							 | 
						||
| 
								 | 
							
								        item = convertFunc(item);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      if (item !== undefined) {
							 | 
						||
| 
								 | 
							
								        setPath(resultRow, head, item, conv,i);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if (hasValue) {
							 | 
						||
| 
								 | 
							
								    return resultRow;
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    return null;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const builtInConv: { [key: string]: CellParser } = {
							 | 
						||
| 
								 | 
							
								  "string": stringType,
							 | 
						||
| 
								 | 
							
								  "number": numberType,
							 | 
						||
| 
								 | 
							
								  "omit": function () { }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								function getConvFunc(head: string, i: number, conv: Converter): CellParser | null {
							 | 
						||
| 
								 | 
							
								  if (conv.parseRuntime.columnConv[i] !== undefined) {
							 | 
						||
| 
								 | 
							
								    return conv.parseRuntime.columnConv[i];
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    let flag = conv.parseParam.colParser[head];
							 | 
						||
| 
								 | 
							
								    if (flag === undefined) {
							 | 
						||
| 
								 | 
							
								      return conv.parseRuntime.columnConv[i] = null;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    if (typeof flag === "object") {
							 | 
						||
| 
								 | 
							
								      flag = (flag as ColumnParam).cellParser || "string";
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    if (typeof flag === "string") {
							 | 
						||
| 
								 | 
							
								      flag = flag.trim().toLowerCase();
							 | 
						||
| 
								 | 
							
								      const builtInFunc = builtInConv[flag];
							 | 
						||
| 
								 | 
							
								      if (builtInFunc) {
							 | 
						||
| 
								 | 
							
								        return conv.parseRuntime.columnConv[i] = builtInFunc;
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        return conv.parseRuntime.columnConv[i] = null;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    } else if (typeof flag === "function") {
							 | 
						||
| 
								 | 
							
								      return conv.parseRuntime.columnConv[i] = flag;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      return conv.parseRuntime.columnConv[i] = null;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								function setPath(resultJson: any, head: string, value: any, conv: Converter,headIdx:number) {
							 | 
						||
| 
								 | 
							
								  if (!conv.parseRuntime.columnValueSetter[headIdx]) {
							 | 
						||
| 
								 | 
							
								    if (conv.parseParam.flatKeys) {
							 | 
						||
| 
								 | 
							
								      conv.parseRuntime.columnValueSetter[headIdx] = flatSetter;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      
							 | 
						||
| 
								 | 
							
								      if (head.indexOf(".") > -1) {
							 | 
						||
| 
								 | 
							
								        const headArr=head.split(".");
							 | 
						||
| 
								 | 
							
								        let jsonHead=true;
							 | 
						||
| 
								 | 
							
								        while(headArr.length>0){
							 | 
						||
| 
								 | 
							
								          const headCom=headArr.shift();
							 | 
						||
| 
								 | 
							
								          if (headCom!.length===0){
							 | 
						||
| 
								 | 
							
								            jsonHead=false;
							 | 
						||
| 
								 | 
							
								            break;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if (!jsonHead || conv.parseParam.colParser[head] && (conv.parseParam.colParser[head] as ColumnParam).flat) {
							 | 
						||
| 
								 | 
							
								          conv.parseRuntime.columnValueSetter[headIdx] = flatSetter;
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								          conv.parseRuntime.columnValueSetter[headIdx] = jsonSetter;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        conv.parseRuntime.columnValueSetter[headIdx] = flatSetter;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if (conv.parseParam.nullObject ===true && value ==="null"){
							 | 
						||
| 
								 | 
							
								    value=null;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  conv.parseRuntime.columnValueSetter[headIdx](resultJson, head, value);
							 | 
						||
| 
								 | 
							
								  // flatSetter(resultJson, head, value);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								function flatSetter(resultJson: any, head: string, value: any) {
							 | 
						||
| 
								 | 
							
								  resultJson[head] = value;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								function jsonSetter(resultJson: any, head: string, value: any) {
							 | 
						||
| 
								 | 
							
								  set(resultJson, head, value);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function checkType(item: string, head: string, headIdx: number, conv: Converter): Function {
							 | 
						||
| 
								 | 
							
								  if (conv.parseRuntime.headerType[headIdx]) {
							 | 
						||
| 
								 | 
							
								    return conv.parseRuntime.headerType[headIdx];
							 | 
						||
| 
								 | 
							
								  } else if (head.indexOf('number#!') > -1) {
							 | 
						||
| 
								 | 
							
								    return conv.parseRuntime.headerType[headIdx] = numberType;
							 | 
						||
| 
								 | 
							
								  } else if (head.indexOf('string#!') > -1) {
							 | 
						||
| 
								 | 
							
								    return conv.parseRuntime.headerType[headIdx] = stringType;
							 | 
						||
| 
								 | 
							
								  } else if (conv.parseParam.checkType) {
							 | 
						||
| 
								 | 
							
								    return conv.parseRuntime.headerType[headIdx] = dynamicType;
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    return conv.parseRuntime.headerType[headIdx] = stringType;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function numberType(item) {
							 | 
						||
| 
								 | 
							
								  var rtn = parseFloat(item);
							 | 
						||
| 
								 | 
							
								  if (isNaN(rtn)) {
							 | 
						||
| 
								 | 
							
								    return item;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return rtn;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function stringType(item: string): string {
							 | 
						||
| 
								 | 
							
								  return item.toString();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function dynamicType(item) {
							 | 
						||
| 
								 | 
							
								  var trimed = item.trim();
							 | 
						||
| 
								 | 
							
								  if (trimed === "") {
							 | 
						||
| 
								 | 
							
								    return stringType(item);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if (numReg.test(trimed)) {
							 | 
						||
| 
								 | 
							
								    return numberType(item);
							 | 
						||
| 
								 | 
							
								  } else if (trimed.length === 5 && trimed.toLowerCase() === "false" || trimed.length === 4 && trimed.toLowerCase() === "true") {
							 | 
						||
| 
								 | 
							
								    return booleanType(item);
							 | 
						||
| 
								 | 
							
								  } else if (trimed[0] === "{" && trimed[trimed.length - 1] === "}" || trimed[0] === "[" && trimed[trimed.length - 1] === "]") {
							 | 
						||
| 
								 | 
							
								    return jsonType(item);
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    return stringType(item);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function booleanType(item) {
							 | 
						||
| 
								 | 
							
								  var trimed = item.trim();
							 | 
						||
| 
								 | 
							
								  if (trimed.length === 5 && trimed.toLowerCase() === "false") {
							 | 
						||
| 
								 | 
							
								    return false;
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    return true;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function jsonType(item) {
							 | 
						||
| 
								 | 
							
								  try {
							 | 
						||
| 
								 | 
							
								    return JSON.parse(item);
							 | 
						||
| 
								 | 
							
								  } catch (e) {
							 | 
						||
| 
								 | 
							
								    return item;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 |