0

I want to convert CSV to JSON file by taking data from stdin and outputting it to stdout. The input data's format has a format (each line) like this: 111117_055958,b8:27:eb:da:ef:6d,0,b8:27:eb:8f:ba:38,192.168.1.10,171110_163200,19,0,0,562,18.7,50.1,ON,OFF,44.0,6593,3697,-2.700629,X

My Python code is:

#!/usr/bin/env python
import csv, json , sys

fieldnames = ("Time","MAC_ETH","IP_ETH","MAC_WiFi","IP_WiFi","Up_time","Winsen","ADC_2","ADC_3","VOC","Temp","Humidity","Internet","Lampa_UV","CPU_temp","Amph_P1","Amph_P2","PT100","Brak",)
reader = csv.DictReader(sys.stdin, fieldnames)

for row in reader:
    print(json.dumps(row, sys.stdout))
    sys.stdout.write('\n')

And my output looks like this:

{"ADC_2": "0", "ADC_3": "0", "Up_time": "171110_163200", "MAC_WiFi": "b8:27:eb:8f:ba:38", "CPU_temp": "44.0", "Temp": "18.7", "VOC": "562", "PT100": "-2.700629", "MAC_ETH": "b8:27:eb:da:ef:6d", "Internet": "ON", "Winsen": "19", "Humidity": "50.1", "Amph_P2": "3697", "Amph_P1": "6593", "IP_ETH": "0", "Time": "111117_055958", "Brak": "X", "Lampa_UV": "OFF", "IP_WiFi": "192.168.1.10"}

So names and values of parameters are OK. But the order of parameters is different compared to the input string and order in the fieldnames value. Can you tell me what I am doing wrong?

I use Python 2.7.12 on Synology.

Payden K. Pringle
  • 61
  • 1
  • 2
  • 19
mackowiakp
  • 203
  • 1
  • 4
  • 12
  • Actually, [this](https://stackoverflow.com/questions/10844064/items-in-json-object-are-out-of-order-using-json-dumps) may be more appropriate since you're `dump`ing, not `load`ing. – glibdud Nov 15 '17 at 16:34
  • 1
    And it would be in combination with @TalSkverer's dupe, since you're using `DictReader`. – glibdud Nov 15 '17 at 16:36
  • Answered your question. Hope it helped, if so please mark as correct and consider an upvote. – alexisdevarennes Nov 15 '17 at 16:37

2 Answers2

1

A workaround to this problem would be to use a normal csv.reader() and to then construct an OrderedDict() with each row. This can then be passed to json.dumps() to maintain the order:

from collections import OrderedDict
import csv, json, sys

fieldnames = ("Time", "MAC_ETH", "IP_ETH", "MAC_WiFi", "IP_WiFi", "Up_time", "Winsen", "ADC_2", "ADC_3", "VOC", "Temp", "Humidity", "Internet", "Lampa_UV", "CPU_temp", "Amph_P1", "Amph_P2", "PT100", "Brak",)

for row in csv.reader(sys.stdin):
    rowd = OrderedDict(zip(fieldnames, row))
    print(json.dumps(rowd, sys.stdout))
    sys.stdout.write('\n')

This would give you output as:

{"Time": "111117_055958", "MAC_ETH": "b8:27:eb:da:ef:6d", "IP_ETH": "0", "MAC_WiFi": "b8:27:eb:8f:ba:38", "IP_WiFi": "192.168.1.10", "Up_time": "171110_163200", "Winsen": "19", "ADC_2": "0", "ADC_3": "0", "VOC": "562", "Temp": "18.7", "Humidity": "50.1", "Internet": "ON", "Lampa_UV": "OFF", "CPU_temp": "44.0", "Amph_P1": "6593", "Amph_P2": "3697", "PT100": "-2.700629", "Brak": "X"}
Martin Evans
  • 45,791
  • 17
  • 81
  • 97
0

json / dict does not preserve key order.

In python > 3.6 dict does support preserving key order by default.

However since reader has a .fieldnames which is order you could do the following (UNTESTED):

for row in reader:
    print(json.dumps({f: row[f] for f in reader.fieldnames}, sys.stdout))
    sys.stdout.write('\n')

Or simply use your own declared fieldnames:

for row in reader:
    print(json.dumps({f: row[f] for f in fieldnames}, sys.stdout))
    sys.stdout.write('\n')
alexisdevarennes
  • 5,437
  • 4
  • 24
  • 38