Предположим, у меня есть структура данных в следующем формате
https://docs.google.com/spreadsheets/d/e/2PACX-1vTFO_MoPwZmvKZOWT2J7kjGr9OC4uUb06zGxOdmXJ8h3FZ2Q0tpsoYH653Pm5mdNcM4Fs7KdlGWSkEy/pubhtml?gid=692973693&single=true
-----------
MovementOfGoods
---| 4.2. MovementOfGoods : N/A
------| 4.2.1. NumberOfMovementLines : Inteiro *
------| 4.2.2. TotalQuantityIssued : Decimal *
------| 4.2.3. StockMovement : N/A
---------| 4.2.3.1. DocumentNumber : Texto 60 *
---------| 4.2.3.2. ATCUD : Texto 100 *
---------| 4.2.3.3. DocumentStatus : N/A *
------------| 4.2.3.3.1. MovementStatus : Texto 1 *
------------| 4.2.3.3.2. MovementStatusDate : Data e Hora *
------------| 4.2.3.3.3. Reason : Texto 50
------------| 4.2.3.3.4. SourceID : Texto 30 *
------------| 4.2.3.3.5. SourceBilling : Texto 1 *
---------| 4.2.3.4. Hash : Texto 172 *
---------| 4.2.3.5. HashControl : Texto 70 *
---------| 4.2.3.6. Period : Inteiro
---------| 4.2.3.7. MovementDate : Data *
---------| 4.2.3.8. MovementType : Texto 2 *
---------| 4.2.3.9. SystemEntryDate : Data e Hora *
---------| 4.2.3.10. TransactionID : Texto 70 **
---------| 4.2.3.11. CustomerID : Texto 30 **
---------| 4.2.3.12. SupplierID : Texto 30 **
---------| 4.2.3.13. SourceID : Texto 30 *
---------| 4.2.3.14. EACCode : Texto 5
---------| 4.2.3.15. MovementComments : Texto 60
---------| 4.2.3.16. ShipTo : N/A
------------| 4.2.3.16.1. DeliveryID : Texto 255
------------| 4.2.3.16.2. DeliveryDate : Data
------------| 4.2.3.16.3. WarehouseID : Texto 50
------------| 4.2.3.16.4. LocationID : Texto 30
------------| 4.2.3.16.5. Address : N/A
---------------| 4.2.3.16.5.1. BuildingNumber : Texto 10
---------------| 4.2.3.16.5.2. StreetName : Texto 200
---------------| 4.2.3.16.5.3. AddressDetail : Texto 210 *
---------------| 4.2.3.16.5.4. City : Texto 50 *
---------------| 4.2.3.16.5.5. PostalCode : Texto 20 *
---------------| 4.2.3.16.5.6. Region : Texto 50
---------------| 4.2.3.16.5.7. Country : Texto 2 *
---------| 4.2.3.17. ShipFrom : N/A
------------| 4.2.3.17.1. DeliveryID : Texto 255
------------| 4.2.3.17.2. DeliveryDate : Data
------------| 4.2.3.17.3. WarehouseID : Texto 50
------------| 4.2.3.17.4. LocationID : Texto 30
------------| 4.2.3.17.5. Address : N/A
---------------| 4.2.3.17.5.1. BuildingNumber : Texto 10
---------------| 4.2.3.17.5.2. StreetName : Texto 200
---------------| 4.2.3.17.5.3. AddressDetail : Texto 210 *
---------------| 4.2.3.17.5.4. City : Texto 50 *
---------------| 4.2.3.17.5.5. PostalCode : Texto 20 *
---------------| 4.2.3.17.5.6. Region : Texto 20
---------------| 4.2.3.17.5.7. Country : Texto 2 *
---------| 4.2.3.18. MovementEndTime : Data e hora
---------| 4.2.3.19. MovementStartTime : Data e hora *
---------| 4.2.3.20. ATDocCodeID : Texto 200
---------| 4.2.3.21. Line : N/A *
------------| 4.2.3.21.1. LineNumber : Inteiro *
------------| 4.2.3.21.2. OrderReferences : N/A
---------------| 4.2.3.21.2.1. OriginatingON : Texto 60
---------------| 4.2.3.21.2.2. OrderDate : Data
------------| 4.2.3.21.3. ProductCode : Texto 60 *
------------| 4.2.3.21.4. ProductDescription : Texto 200 *
------------| 4.2.3.21.5. Quantity : Decimal *
------------| 4.2.3.21.6. UnitOfMeasure : Texto 20 *
------------| 4.2.3.21.7. UnitPrice : Monetário *
------------| 4.2.3.21.8. Description : Texto 200 *
------------| 4.2.3.21.9. ProductSerialNumber : N/A
---------------| 4.2.3.21.9.1. SerialNumber : Texto 100 *
------------| 4.2.3.21.10. DebitAmount : Monetário **
------------| 4.2.3.21.11. CreditAmount : Monetário **
------------| 4.2.3.21.12. Tax : N/A **
---------------| 4.2.3.21.12.1. TaxType : Texto 3 *
---------------| 4.2.3.21.12.2. TaxCountryRegion : Texto 5 *
---------------| 4.2.3.21.12.3. TaxCode : Texto 10 *
---------------| 4.2.3.21.12.4. TaxPercentage : Decimal *
------------| 4.2.3.21.13. TaxExemptionReason : Texto 60 **
------------| 4.2.3.21.14. TaxExemptionCode : Texto 3 **
------------| 4.2.3.21.15. SettlementAmount : Monetário
------------| 4.2.3.21.16. CustomsInformation : N/A
---------------| 4.2.3.21.16.1. ARCNo : Texto 21
---------------| 4.2.3.21.16.2. IECAmount : Monetário
---------| 4.2.3.22. DocumentTotals : N/A *
------------| 4.2.3.22.1. TaxPayable : Monetário *
------------| 4.2.3.22.2. NetTotal : Monetário *
------------| 4.2.3.22.3. GrossTotal : Monetário *
------------| 4.2.3.22.4. Currency : N/A
---------------| 4.2.3.22.4.1. CurrencyCode : Texto 3 *
---------------| 4.2.3.22.4.2. CurrencyAmount : Monetário *
---------------| 4.2.3.22.4.3. ExchangeRate : Decimal *
[Embedded structures]
~> MovementOfGoods
~> StockMovement
~> DocumentStatus
~> ShipTo
~> Address
~> ShipFrom
~> Address
~> Line
~> OrderReferences
~> ProductSerialNumber
~> Tax
~> CustomsInformation
~> DocumentTotals
~> Currency
, которую я хотел бы проанализировать в JSON со встроенными объектами, чтобы следовать иерархии, созданнойнумерация.
Выше приведен синтаксический анализ файла tsv, экспортированного из Google Sheets, https://docs.google.com/spreadsheets/d/e/2PACX-1vTFO_MoPwZmvKZOWT2J7kjGr9OC4uUb06zGxOdmXJ8h3FZ2Q0tpsoYH653Pm5mdNcM4Fs7KdlGWSkEy/pubhtml?gid=692973693&single=true
Я полагаю, что алгоритм для этого должен был бы знать, какой "уровень"каждая строка, когда собирается сделать новый отступ, в новый объект, новые, даже встроенные объекты внутри него, а затем обратно в корень, как, например, в
-----------
Customer
---| 2.2.1. CustomerID : Texto 30 *
---| 2.2.2. AccountID : Texto 30 *
---| 2.2.3. CustomerTaxID : Texto 30 *
---| 2.2.4. CompanyName : Texto 100 *
---| 2.2.5. Contact : Texto 50
---| 2.2.6. BillingAddress : N/A *
------| 2.2.6.1. BuildingNumber : Texto 10
------| 2.2.6.2. StreetName : Texto 200
------| 2.2.6.3. AddressDetail : Texto 210 *
------| 2.2.6.4. City : Texto 50 *
------| 2.2.6.5. PostalCode : Texto 20 *
------| 2.2.6.6. Region : Texto 50
------| 2.2.6.7. Country : Texto 12 *
---| 2.2.7. ShipToAddress : N/A
------| 2.2.7.1. BuildingNumber : Texto 10
------| 2.2.7.2. StreetName : Texto 200
------| 2.2.7.3. AddressDetail : Texto 210 *
------| 2.2.7.4. City : Texto 50 *
------| 2.2.7.5. PostalCode : Texto 20 *
------| 2.2.7.6. Region : Texto 50
------| 2.2.7.7. Country : Texto 12 *
---| 2.2.8. Telephone : Texto 20
---| 2.2.9. Fax : Texto 20
---| 2.2.10. Email : Texto 60
---| 2.2.11. Website : Texto 60
---| 2.2.12. SelfBillingIndicator : Inteiro *
[Embedded structures]
~> BillingAddress
~> ShipToAddress
.
Мой текущий код просматривает список и определяет, какие из них являются встроенными структурами, но не может отследить, в какую из этих структур следует встроить, поэтому иерархия теряется или фактически является визуальной.После просмотра каждого листа «[встроенные структуры]» отображаются в списке, но не в виде дерева.
var request = require('request')
url = "https://docs.google.com/spreadsheets/d/e/2PACX-1vTFO_MoPwZmvKZOWT2J7kjGr9OC4uUb06zGxOdmXJ8h3FZ2Q0tpsoYH653Pm5mdNcM4Fs7KdlGWSkEy/pub?gid=692973693&single=true&output=tsv"
request(url, function (error, response, body) {
if (body != undefined) {
let lines = body.split('\r')
let lastLevel = 0
let dataStructs = [];
lines.forEach(function(line, index) {
if (index != 0) {
columns = line.split('\t')
let currentLevel = (columns[0].trim().split(".").length - 1)
if (index == 1) {
initialLevel = currentLevel;
}
if (columns[5].toLowerCase() == 'n/a') dataStructs.push(columns[2]);
if (currentLevel !== lastLevel) {
if (currentLevel > lastLevel) {
console.log(columns[0].trim(), columns[2].trim(), ':', columns[5].trim(), columns[1].trim())
} else if (currentLevel < lastLevel) {
console.log(columns[0].trim(), columns[2].trim(), ':', columns[5].trim(), columns[1].trim())
}
lastLevel = currentLevel
} else {
console.log(columns[0].trim(), columns[2].trim(), ':', columns[5].trim(), columns[1].trim())
}
}
});
console.log('\n[Embedded structures]')
dataStructs.forEach(struct => {
console.log('~>', struct/* , '=', modelName+struct, '?' */)
})
console.log('\n')
}
})
Приведенный выше код выведет
4.2. MovementOfGoods : N/A
4.2.1. NumberOfMovementLines : Inteiro *
4.2.2. TotalQuantityIssued : Decimal *
4.2.3. StockMovement : N/A
4.2.3.1. DocumentNumber : Texto 60 *
4.2.3.2. ATCUD : Texto 100 *
4.2.3.3. DocumentStatus : N/A *
4.2.3.3.1. MovementStatus : Texto 1 *
4.2.3.3.2. MovementStatusDate : Data e Hora *
4.2.3.3.3. Reason : Texto 50
4.2.3.3.4. SourceID : Texto 30 *
4.2.3.3.5. SourceBilling : Texto 1 *
4.2.3.4. Hash : Texto 172 *
4.2.3.5. HashControl : Texto 70 *
4.2.3.6. Period : Inteiro
4.2.3.7. MovementDate : Data *
4.2.3.8. MovementType : Texto 2 *
4.2.3.9. SystemEntryDate : Data e Hora *
4.2.3.10. TransactionID : Texto 70 **
4.2.3.11. CustomerID : Texto 30 **
4.2.3.12. SupplierID : Texto 30 **
4.2.3.13. SourceID : Texto 30 *
4.2.3.14. EACCode : Texto 5
4.2.3.15. MovementComments : Texto 60
4.2.3.16. ShipTo : N/A
4.2.3.16.1. DeliveryID : Texto 255
4.2.3.16.2. DeliveryDate : Data
4.2.3.16.3. WarehouseID : Texto 50
4.2.3.16.4. LocationID : Texto 30
4.2.3.16.5. Address : N/A
4.2.3.16.5.1. BuildingNumber : Texto 10
4.2.3.16.5.2. StreetName : Texto 200
4.2.3.16.5.3. AddressDetail : Texto 210 *
4.2.3.16.5.4. City : Texto 50 *
4.2.3.16.5.5. PostalCode : Texto 20 *
4.2.3.16.5.6. Region : Texto 50
4.2.3.16.5.7. Country : Texto 2 *
4.2.3.17. ShipFrom : N/A
4.2.3.17.1. DeliveryID : Texto 255
4.2.3.17.2. DeliveryDate : Data
4.2.3.17.3. WarehouseID : Texto 50
4.2.3.17.4. LocationID : Texto 30
4.2.3.17.5. Address : N/A
4.2.3.17.5.1. BuildingNumber : Texto 10
4.2.3.17.5.2. StreetName : Texto 200
4.2.3.17.5.3. AddressDetail : Texto 210 *
4.2.3.17.5.4. City : Texto 50 *
4.2.3.17.5.5. PostalCode : Texto 20 *
4.2.3.17.5.6. Region : Texto 20
4.2.3.17.5.7. Country : Texto 2 *
4.2.3.18. MovementEndTime : Data e hora
4.2.3.19. MovementStartTime : Data e hora *
4.2.3.20. ATDocCodeID : Texto 200
4.2.3.21. Line : N/A *
4.2.3.21.1. LineNumber : Inteiro *
4.2.3.21.2. OrderReferences : N/A
4.2.3.21.2.1. OriginatingON : Texto 60
4.2.3.21.2.2. OrderDate : Data
4.2.3.21.3. ProductCode : Texto 60 *
4.2.3.21.4. ProductDescription : Texto 200 *
4.2.3.21.5. Quantity : Decimal *
4.2.3.21.6. UnitOfMeasure : Texto 20 *
4.2.3.21.7. UnitPrice : Monetário *
4.2.3.21.8. Description : Texto 200 *
4.2.3.21.9. ProductSerialNumber : N/A
4.2.3.21.9.1. SerialNumber : Texto 100 *
4.2.3.21.10. DebitAmount : Monetário **
4.2.3.21.11. CreditAmount : Monetário **
4.2.3.21.12. Tax : N/A **
4.2.3.21.12.1. TaxType : Texto 3 *
4.2.3.21.12.2. TaxCountryRegion : Texto 5 *
4.2.3.21.12.3. TaxCode : Texto 10 *
4.2.3.21.12.4. TaxPercentage : Decimal *
4.2.3.21.13. TaxExemptionReason : Texto 60 **
4.2.3.21.14. TaxExemptionCode : Texto 3 **
4.2.3.21.15. SettlementAmount : Monetário
4.2.3.21.16. CustomsInformation : N/A
4.2.3.21.16.1. ARCNo : Texto 21
4.2.3.21.16.2. IECAmount : Monetário
4.2.3.22. DocumentTotals : N/A *
4.2.3.22.1. TaxPayable : Monetário *
4.2.3.22.2. NetTotal : Monetário *
4.2.3.22.3. GrossTotal : Monetário *
4.2.3.22.4. Currency : N/A
4.2.3.22.4.1. CurrencyCode : Texto 3 *
4.2.3.22.4.2. CurrencyAmount : Monetário *
4.2.3.22.4.3. ExchangeRate : Decimal *
[Embedded structures]
~> MovementOfGoods
~> StockMovement
~> DocumentStatus
~> ShipTo
~> Address
~> ShipFrom
~> Address
~> Line
~> OrderReferences
~> ProductSerialNumber
~> Tax
~> CustomsInformation
~> DocumentTotals
~> Currency
Как можно пройти по этим спискам и добавить поля / свойства к правым внедренным объектам или к корню объекта в древовидной форме?
edit:
На примере приведенного выше "Customer" с табличной структурой, такой как https://docs.google.com/spreadsheets/d/e/2PACX-1vTFO_MoPwZmvKZOWT2J7kjGr9OC4uUb06zGxOdmXJ8h3FZ2Q0tpsoYH653Pm5mdNcM4Fs7KdlGWSkEy/pubhtml?gid=700343422&single=true, желаемый результат будет
{
"Customer": {
"2.2.1. CustomerID": "Texto 30 *",
"2.2.2. AccountID": "Texto 30 *",
"2.2.3. CustomerTaxID": "Texto 30 *",
"2.2.4. CompanyName": "Texto 100 *",
"2.2.5. Contact": "Texto 50",
"2.2.6. BillingAddress": {
"2.2.6.1. BuildingNumber": "Texto 10",
"2.2.6.2. StreetName": "Texto 200",
"2.2.6.3. AddressDetail": "Texto 210 *",
"2.2.6.4. City": "Texto 50 *",
"2.2.6.5. PostalCode": "Texto 20 *",
"2.2.6.6. Region": "Texto 50 ",
"2.2.6.7. Country": "Texto 12 *"
},
"2.2.7. ShipToAddress": {
"2.2.7.1. BuildingNumber": "Texto 10",
"2.2.7.2. StreetName": "Texto 200",
"2.2.7.3. AddressDetail": "Texto 210 *",
"2.2.7.4. City": "Texto 50 *",
"2.2.7.5. PostalCode": "Texto 20 *",
"2.2.7.6. Region": "Texto 50",
"2.2.7.7. Country": "Texto 12 *"
},
"2.2.8. Telephone ": "Texto 20",
"2.2.9. Fax": "Texto 20",
"2.2.10. Email": "Texto 60",
"2.2.11. Website": "Texto 60",
"2.2.12. SelfBillingIndicator": "Inteiro *"
}
}
edit 2: Чтобы было ясно, желаемый «результат» должен быть в состоянии определить, когда вложенные объекты начинаются и заканчиваются, а также вкладывать их в нужное место в соответствии ск исходной таблице.Конкретные столбцы из таблицы, передаваемой в JSON, могут различаться, также как и фактический используемый синтаксис, измененный с JSON на, скажем, генераторы rails.Чего мне не хватает, так это части кода «определение уровня».
edit 3:
var request = require('request')
url = "https://docs.google.com/spreadsheets/d/e/2PACX-1vTFO_MoPwZmvKZOWT2J7kjGr9OC4uUb06zGxOdmXJ8h3FZ2Q0tpsoYH653Pm5mdNcM4Fs7KdlGWSkEy/pub?gid=700343422&single=true&output=tsv"
request(url, function (error, response, body) {
if (body != undefined) {
let lines = body.split('\r')
let lastLevel = 0
let dataStructs = [];
goneUpCounter = 0;
console.log("{")
lines.forEach(function (line, index) {
if (index != 0) {
columns = line.split('\t')
let currentLevel = (columns[0].trim().split(".").length - 1)
if (columns[5].toLowerCase() == 'n/a') {
dataStructs.push(columns[2]);
goneUpCounter += 1;
}
if (currentLevel !== lastLevel) {
if (currentLevel > lastLevel) {
if (columns[5].toLowerCase() == 'n/a') {
console.log("{\"" + columns[2].trim() + "\" : {")
} else {
console.log("\"" + columns[0].trim(), columns[2].trim() + "\"", ':', "\"" + columns[5].trim(), columns[1].trim() + "\",")
}
} else if (currentLevel < lastLevel) {
if (columns[5].toLowerCase() == 'n/a') {
console.log("\"" + columns[2].trim() + "\" : {")
} else {
console.log("\"" + columns[0].trim(), columns[2].trim() + "\"", ':', "\"" + columns[5].trim(), columns[1].trim() + "\",")
}
}
lastLevel = currentLevel
} else {
if (columns[5].toLowerCase() == 'n/a') {
console.log("\"" + columns[2].trim() + "\" : {")
} else {
if ((lines[index + 1] != undefined && lines[index + 1].split('\t')[0].trim().split('.').length - 1 < lastLevel) || index + 1 == lines.length) {
console.log("\"" + columns[0].trim(), columns[2].trim() + "\"", ':', "\"" + columns[5].trim(), columns[1].trim() + "\"")
} else {
console.log("\"" + columns[0].trim(), columns[2].trim() + "\"", ':', "\"" + columns[5].trim(), columns[1].trim() + "\",")
}
}
if (lines[index + 1] != undefined && lines[index + 1].split('\t')[0].trim().split('.').length - 1 < lastLevel) {
goneUpCounter -= 1;
console.log('},')
}
}
}
});
for (let i = 0; i < goneUpCounter + 1; i++) {
console.log('}')
}
}
})
возвращает допустимый JSON, но код просто ужасен.
{
"2.2.1. CustomerID": "Texto 30 *",
"2.2.2. AccountID": "Texto 30 *",
"2.2.3. CustomerTaxID": "Texto 30 *",
"2.2.4. CompanyName": "Texto 100 *",
"2.2.5. Contact": "Texto 50 ",
"BillingAddress": {
"2.2.6.1. BuildingNumber": "Texto 10 ",
"2.2.6.2. StreetName": "Texto 200 ",
"2.2.6.3. AddressDetail": "Texto 210 *",
"2.2.6.4. City": "Texto 50 *",
"2.2.6.5. PostalCode": "Texto 20 *",
"2.2.6.6. Region": "Texto 50 ",
"2.2.6.7. Country": "Texto 12 *"
},
"ShipToAddress": {
"2.2.7.1. BuildingNumber": "Texto 10 ",
"2.2.7.2. StreetName": "Texto 200 ",
"2.2.7.3. AddressDetail": "Texto 210 *",
"2.2.7.4. City": "Texto 50 *",
"2.2.7.5. PostalCode": "Texto 20 *",
"2.2.7.6. Region": "Texto 50 ",
"2.2.7.7. Country": "Texto 12 *"
},
"2.2.8. Telephone": "Texto 20 ",
"2.2.9. Fax": "Texto 20 ",
"2.2.10. Email": "Texto 60 ",
"2.2.11. Website": "Texto 60 ",
"2.2.12. SelfBillingIndicator": "Inteiro *"
}