Giữ thứ tự của các khóa JSON trong quá trình chuyển đổi JSON thành CSV


82

Tôi đang sử dụng thư viện JSON được cung cấp tại đây http://www.json.org/java/index.html để chuyển đổi chuỗi json mà tôi có thành CSV. Nhưng vấn đề tôi gặp phải là, thứ tự của các phím bị mất sau khi chuyển đổi.

Đây là mã chuyển đổi:

    JSONObject jo = new JSONObject(someString);
    JSONArray ja = jo.getJSONArray("items");
    String s = CDL.toString(ja);
    System.out.println(s);

Đây là nội dung của "someString":

{
    "items":
    [
        {
            "WR":"qwe",
            "QU":"asd",
            "QA":"end",
            "WO":"hasd",
            "NO":"qwer"
        },
    ]
}

Đây là kết quả:

WO,QU,WR,QA,NO
hasd,asd,qwe,end,qwer

Trong khi những gì tôi mong đợi là giữ thứ tự của các phím:

WR,QU,QA,WO,NO
qwe,asd,end,hasd,qwer

Có cách nào tôi có thể có kết quả này bằng cách sử dụng thư viện này không? Nếu không, có thư viện nào khác sẽ cung cấp khả năng giữ thứ tự các khóa trong kết quả không?


4
Từ điển không được sắp xếp. Tôi thậm chí không nghĩ rằng JSON đảm bảo đơn đặt hàng.
Falmarri

2
Cảm ơn bạn về thông tin. Nhưng tôi không có lựa chọn nào khác ngoài việc sử dụng JSON trong ứng dụng của mình và ứng dụng của tôi cần phải giữ thứ tự của các khóa :(
Hery

Trong trường hợp của tôi, vấn đề không phải là thiếu thứ tự mà là nó không mang tính xác định. Đôi khi tôi nhận được chìa khóa footrước khi chìa khóa barvà đôi khi bartrước đó foo. Điều này gây khó khăn cho việc viết bài kiểm tra.
Sridhar Sarnobat

Tôi cũng gặp phải nhu cầu này, nhưng đó là để so sánh nhật ký nhanh trong quá trình thử nghiệm thời gian thực. Tôi cần so sánh các bản ghi mới được tạo với các bản ghi đã tạo trước đó trong thời gian thực để có một ứng dụng được thực hiện nhiều. Có nhiều cách khác để làm điều đó, nhưng tôi muốn nhật ký ở định dạng JSON. Tuy nhiên, để giảm thiểu việc sử dụng CPU, tôi đang viết trình viết JSON trực tiếp thành chuỗi của riêng mình. Tôi hoàn toàn không cần cấu trúc bên trong và tôi có thể duy trì thứ tự khóa để so sánh chuỗi nhật ký nhanh chóng. Có những lý do chính đáng để muốn thứ tự có thể đoán trước được.
Joe Lapp

viết mã của riêng bạn để chuyển đổi JSON thành tệp CSV được sắp xếp cụ thể, theo cách đó bạn tôn trọng những gì cả hai định dạng phải có.
Martijn Scheffer

Câu trả lời:


95

Có nhiều cách (hacky) để làm điều đó ... nhưng bạn không nên.

Trong JSON, một đối tượng được định nghĩa như vậy:

Một đối tượng là một tập hợp các cặp tên / giá trị không có thứ tự.

Xem http://json.org .

Hầu hết các triển khai JSON đều không cố gắng duy trì thứ tự của các cặp tên / giá trị của một đối tượng, vì nó (theo định nghĩa) không đáng kể.

Nếu bạn muốn thứ tự được giữ nguyên, bạn cần xác định lại cấu trúc dữ liệu của mình; ví dụ

{
    "items":
    [
        [
            {"WR":"qwe"},
            {"QU":"asd"},
            {"QA":"end"},
            {"WO":"hasd"},
            {"NO":"qwer"}
        ],
    ]
}

hoặc đơn giản hơn:

{
    "items":
    [
        {"WR":"qwe"},
        {"QU":"asd"},
        {"QA":"end"},
        {"WO":"hasd"},
        {"NO":"qwer"}
    ]
}

THEO SÁT

Cảm ơn bạn đã cung cấp thông tin, nhưng tôi không có lựa chọn nào khác ngoài việc sử dụng JSON trong ứng dụng của mình và ứng dụng của tôi cần giữ thứ tự của các khóa bất kể định nghĩa của đối tượng JSON là gì ... Tôi không được phép thay đổi định dạng của tệp JSON cũng...

Bạn cần có một cuộc trò chuyện khó khăn với người đã thiết kế cấu trúc tệp đó và sẽ không cho phép bạn thay đổi cấu trúc đó. Đó là / họ rõ ràng là sai. Bạn cần thuyết phục họ.

Nếu họ thực sự không cho phép bạn thay đổi nó:

  • Bạn nên kiên quyết không gọi nó là JSON ... 'vì nó không phải vậy.
  • Bạn nên chỉ ra rằng bạn sẽ phải viết / sửa đổi mã đặc biệt để xử lý định dạng "không phải JSON" này ... trừ khi bạn có thể tìm thấy một số triển khai JSON duy trì thứ tự. Nếu họ là khách hàng trả tiền, hãy đảm bảo rằng họ trả tiền cho công việc bạn phải làm.
  • Bạn nên chỉ ra rằng nếu "không phải JSON" cần được sử dụng bởi một số công cụ khác, thì nó sẽ có vấn đề. Thật vậy, vấn đề này sẽ xảy ra lặp đi lặp lại ...

Loại điều này thực sự tồi tệ. Một mặt, phần mềm của bạn sẽ vi phạm đặc điểm kỹ thuật lâu đời / đã được thiết lập tốt được thiết kế để thúc đẩy khả năng tương tác. Mặt khác, các nit-wits đã thiết kế định dạng tệp khập khiễng này (không phải JSON!) Có thể đang xỉa xói hệ thống của người khác, v.v. vì hệ thống không thể đối phó với những điều vô nghĩa của chúng .

CẬP NHẬT

Nó cũng đáng đọc những gì JSON RFC (RFC 7159) nói về chủ đề này. Dưới đây là một số đoạn trích:

Trong những năm kể từ khi xuất bản RFC 4627, JSON đã được sử dụng rất rộng rãi. Trải nghiệm này đã tiết lộ một số mẫu nhất định, mặc dù được thông số kỹ thuật cho phép, nhưng đã gây ra các vấn đề về khả năng tương tác.

JavaScript Object Notation (JSON) là một định dạng văn bản để tuần tự hóa dữ liệu có cấu trúc. ...

JSON có thể đại diện cho bốn kiểu nguyên thủy (chuỗi, số, boolean và null) và hai kiểu có cấu trúc (đối tượng và mảng).

Đối tượng là một tập hợp không có thứ tự gồm không hoặc nhiều cặp tên / giá trị, trong đó tên là một chuỗi và một giá trị là một chuỗi, số, boolean, null, đối tượng hoặc mảng.

Các thư viện phân tích cú pháp JSON đã được quan sát thấy có sự khác biệt về việc chúng có hiển thị thứ tự của các thành viên đối tượng đối với phần mềm gọi hay không. Các triển khai có hành vi không phụ thuộc vào thứ tự của thành viên sẽ có thể tương tác với nhau theo nghĩa là chúng sẽ không bị ảnh hưởng bởi những khác biệt này.


6
@Hery - hóa đơn họ :-)
Stephen C

3
@YogeshSomani - "giải pháp" là nắm giữ một thư viện JSON thích hợp và "hack" nó để nó duy trì thứ tự khóa. Xem câu trả lời của gary để làm ví dụ. Nhưng bạn không nên mong đợi một thư viện JSON tiêu chuẩn thực hiện điều này bởi vì nó là một Ý TƯỞNG XẤU để khuyến khích việc lạm dụng đặc tả JSON như thế này. Giải pháp thực sự là sửa ứng dụng của bạn để sử dụng JSON đúng cách.
Stephen C

10
Thật tuyệt khi trở nên tinh khiết nhất và tuyệt đối, nhưng đừng tự đùa, có những trường hợp trong thế giới thực trong đó tệp JSON cần thứ tự của các giá trị đã xác định của nó được bảo toàn. Để thông qua và chấp nhận chúng theo bất kỳ thứ tự nào là một cách tiếp cận json cơ bản, nhưng tôi cho rằng điều đó khác với khả năng có thể lấy một tài liệu json và tuần tự hóa / giải mã hóa trong bình đẳng. Đó là một trường hợp sử dụng phổ biến để có để có một tài liệu json và sử dụng nó để tạo thành một tài liệu của người khác WDDX tiêu chuẩn, HTML, vv nơi nhu cầu đặt hàng để được bảo tồn
Andrew Norman

3
@AndrewNorman - Nếu những gì bạn nói về "nhu cầu" thực sự đúng, thì thông số kỹ thuật nên và sẽ được thay đổi. Thực tế là có thể dễ dàng trình bày thứ tự theo các cách khác trong JSON.
Stephen C

2
JSON chỉ yêu cầu thông tin không được mã hóa theo thứ tự các khóa; nó không phải là JSON khác. Tính nhất quán của tuần tự hóa là một vấn đề khác. Trong một ứng dụng duy nhất, tính nhất quán thường có thể được đảm bảo bằng cách sử dụng thư viện JSON chung, nhưng vẫn có những trường hợp ngoại lệ, chẳng hạn như khi một giải pháp mở rộng trên nhiều nền tảng hoặc khuôn khổ. Trong những trường hợp này, bạn phải tìm cách đối phó với sự không nhất quán (dẫn đến sự kém hiệu quả), hoặc bạn phải tìm cách đảm bảo tính nhất quán. Cả hai cách tiếp cận đều hợp lệ.
Joe Lapp

47

Nó là khá đơn giản để duy trì trật tự. Tôi đã gặp vấn đề tương tự với việc duy trì thứ tự từ lớp DB sang Lớp giao diện người dùng.

Mở tệp JSONObject.java. Nó sử dụng nội bộ HashMap không duy trì thứ tự.

Thay đổi nó thành LinkedHashMap:

    //this.map = new HashMap();
    this.map = new LinkedHashMap();

Điều này đã làm việc cho tôi. Hãy cho tôi biết ở phần bình luận. Tôi đề nghị bản thân thư viện JSON nên có một lớp JSONObject khác duy trì thứ tự, như JSONOrderdObject.java. Tôi rất kém trong việc chọn tên.


2
svn thanh toán json-đơn giản. sửa đổi tệp org.json.simple.JSONObject, <code> JOSNObject mở rộng LinkedHashMap ... </code> từ <code> .. HashMap .. </code>, sửa lỗi nhập và nó hoạt động cho tôi. v1.1.1.
Marku

2
Đây là một giải pháp một dòng tuyệt vời mà tôi chưa bao giờ nghĩ sẽ thử. Hoạt động hoàn hảo và tôi không phải thay đổi bất kỳ mã nào khác của mình. +1
DaaaahWhoosh

Sửa chữa tuyệt vời. Bạn là một anh hùng, thưa ngài
Gregory Nowakowski,

không hoạt động, tôi đã thêm nhập, thay đổi nó như bạn nói, thậm chí đã cố gắng làm như thế này: this.map = new LinkedHashMap<String, Object>();vẫn không hoạt động. Xin vui lòng giúp đỡ ?
Tarek

4
Haha, thật á? Sửa đổi thư viện JSON để đáp ứng nhu cầu của bạn? Tôi có thể tưởng tượng điều này sẽ đi xuống trong cơ sở kiến ​​thức của công ty. "Thực hiện cài đặt sạch mvn của bạn, tải xuống jar, tìm nó, dịch ngược nó, sau đó thay thế HashMap bằng LinkedHashMap". Điều này sẽ hoạt động tốt cho nhiều nhóm nhà phát triển (không).
Chris Neve

22

JSONObject.javalấy bất kỳ bản đồ nào bạn vượt qua. Nó có thể là LinkedHashMaphoặc TreeMapvà sẽ hashmapchỉ mất khi bản đồ trống.

Đây là hàm tạo của JSONObject.javalớp sẽ thực hiện việc kiểm tra bản đồ.

 public JSONObject(Map paramMap)
  {
    this.map = (paramMap == null ? new HashMap() : paramMap);
  }

Vì vậy, trước khi xây dựng một cấu trúc đối tượng json LinkedHashMapvà sau đó chuyển nó cho hàm tạo như thế này,

LinkedHashMap<String, String> jsonOrderedMap = new LinkedHashMap<String, String>();

jsonOrderedMap.put("1","red");
jsonOrderedMap.put("2","blue");
jsonOrderedMap.put("3","green");

JSONObject orderedJson = new JSONObject(jsonOrderedMap);

JSONArray jsonArray = new JSONArray(Arrays.asList(orderedJson));

System.out.println("Ordered JSON Fianl CSV :: "+CDL.toString(jsonArray));

Vì vậy không cần thiết phải thay đổi JSONObject.javalớp. Hy vọng nó sẽ giúp ai đó.


3
Câu trả lời tốt, hoạt động cho java bình thường, nhưng không hoạt động trên Android. Tôi kiểm tra org.json.JSONObject trong android, thật đáng tiếc khi android vẫn sử dụng hashmap được tạo trong nội bộ. Nó chỉ sao chép các cặp tên / giá trị từ paramMap sang HashMap ... :(
正宗 白 布鞋 Ngày

Tôi đã ra lệnh cho JsonObject nhưng khi tôi cố gắng thêm đối tượng đó vào JsonArray, nó cho tôi một đối tượng không có thứ tự. Tôi cần đặt đối tượng vào mảng, tôi cần các đối tượng của mảng sau đó tôi đặt tiêu đề cho mảng và gửi lại. Ví dụ: một đối tượng; {CUSTOMER_SECTOR_ID = 611, CUSTOMER_NO = 0000003204, CUSTOMER_NAME = MARMARİS - KARAS GIDA KARAS TÜKETİM MADDELERİ GIDA LOJ.} Tôi nhận được điều này Nếu tôi đặt hai đối tượng vào mảng: [{"CUSTOMER_NAME": "SILA GIDA", "SILST" GIDA 0000003122 "," CUSTOMER_SECTOR_ID ":" 611 "}, {" CUSTOMER_NAME ":" M ":" 0013114714 "," CUSTOMER_SECTOR_ID ":" 611 "}] Như bạn thấy là sai. Làm thế nào tôi có thể sửa chữa nó
Sahin Yanlık

2
@Deepak Nagaraj. Tôi đã thử giải pháp của bạn nhưng nó không hoạt động, JSONObjectkhông được đặt hàng như của tôi LinkedHashMap. Bạn có phải là usin org.jsonlib?
Ismail Sen

1
Đây không phải là org.jsonmột .. Nó xác định HashMapnội bộ, bất cứ điều gì Mapbạn cung cấp cho nó: @Deepak, bạn có thể chỉ cho chúng tôi cách triển khai mà bạn đã sử dụng không?
Campa

8
Điều này sẽ không hoạt động với org.jsonthư viện. Khi bạn xây dựng một JSONObjectđối tượng mới , chuyển một bản đồ làm đối số, nó sẽ luôn được chuyển đổi thành a HashMap. Phương thức khởi tạo trước hết tạo một bản đồ mới: this.map = new HashMap<String, Object>();và sau đó lặp qua bản đồ của bạn, sao chép mọi phần tử vào bản đồ của mình HashMap.
itachi

13

Một giải pháp dài dòng hơn, nhưng có thể áp dụng rộng rãi cho loại vấn đề này là sử dụng một cặp cấu trúc dữ liệu: một danh sách để chứa thứ tự và một bản đồ để chứa các quan hệ.

Ví dụ:

{
    "items":
    [
        {
            "WR":"qwe",
            "QU":"asd",
            "QA":"end",
            "WO":"hasd",
            "NO":"qwer"
        },
    ],
    "itemOrder":
        ["WR", "QU", "QA", "WO", "NO"]
}

Bạn lặp lại danh sách itemOrder và sử dụng chúng để tra cứu các giá trị bản đồ. Thứ tự được bảo toàn, không có kludges.

Tôi đã sử dụng phương pháp này nhiều lần.


Điều này trở nên phức tạp nếu bản đồ của bạn không chỉ đơn giản cặp khóa-giá trị ...
zfj3ub94rf576hc4eegm

10

Một giải pháp hacky khác sử dụng phản xạ:

JSONObject json = new JSONObject();
Field map = json.getClass().getDeclaredField("map");
map.setAccessible(true);//because the field is private final...
map.set(json, new LinkedHashMap<>());
map.setAccessible(false);//return flag

1
Tôi không nhận được câu trả lời của bạn
M. Usman Khan

1
Mẹo là sửa đổi nội bộ lớp để sử dụng LinkedHashMap thay vì HashMap mặc định, làm cho đối tượng JSON có dữ liệu theo thứ tự bạn đưa chúng vào, điều này không được sắp xếp trực tiếp nhưng nó hoạt động với tôi vì dữ liệu đã được phân tích cú pháp đã được sắp xếp. .
fabe

có vẻ tốt, nhưng làm thế nào để phân tích cú pháp Json String SAU KHI map.set (json, LinkedHashMap mới <> ()); bởi vì Json String được truyền trong hàm tạo phải không? như, JSONObject mới (jsonString).
M. Usman Khan,

Ngoài ra, điều này không hoạt động. không có trường "bản đồ", có trường "nameValuePairs" đã được LinckedHashMap và nó vẫn không hoạt động.
M. Usman Khan

1
Bạn đang sử dụng cách triển khai JSONObject nào? Tôi đang sử dụng org.json phiên bản 20140107 và phải duy trì thứ tự và đó là cách nó hoạt động đối với tôi.
fabe


4

Chỉ tình cờ gặp phải vấn đề tương tự, tôi tin rằng giải pháp cuối cùng mà tác giả sử dụng là sử dụng ContainerFactory tùy chỉnh:

public static Values parseJSONToMap(String msgData) {
    JSONParser parser = new JSONParser();
    ContainerFactory containerFactory = new ContainerFactory(){
        @Override
        public Map createObjectContainer() {
            return new LinkedHashMap();
        }

        @Override
        public List creatArrayContainer() {
            return null;
        }
    };
    try {
        return (Map<String,Object>)parser.parse(msgData, containerFactory);
    } catch (ParseException e) {
        log.warn("Exception parsing JSON string {}", msgData, e);
    }
    return null;
}  

xem http://juliusdavies.ca/json-simple-1.1.1-javadocs/org/json/simple/parser/JSONParser.html#parse(java.io.Reader,org.json.simple.parser.ContainerFactory)


giải pháp thực sự rất tốt và thiết thực. Làm thế nào về cách viết phương thức local ẩn danh lớp bên trong cho containerFactory?
Shailesh Saxena,

3

Đã giải quyết.

Tôi đã sử dụng thư viện JSON.simple từ đây https://code.google.com/p/json-simple/ để đọc chuỗi JSON nhằm giữ thứ tự các khóa và sử dụng thư viện JavaCSV từ đây http://sourceforge.net/ project / javacsv / để chuyển đổi sang định dạng CSV.


Tôi ngạc nhiên rằng điều này đã hiệu quả. Theo cách đọc của tôi về cả mã và nhận xét của lớp JSONObject ( code.google.com/p/json-simple/source/browse/trunk/src/main/java/… ), nó không làm bất cứ điều gì để bảo tồn thứ tự của các phím.
Stephen C

1
Tôi đã không chỉ định giải pháp đầy đủ ở đây, nhưng ý chính của nó là json-simple cung cấp một nhà máy mà bạn có thể chỉ định cấu trúc dữ liệu được sử dụng để lưu trữ các đối tượng json. Chỉ cần chỉ định sử dụng LinkedHashMap.
Hery

@ Rất mong, tôi đang gặp phải vấn đề tương tự nhưng tôi không thể giải quyết nó. Tôi sử dụng org.jsonđể chuyển đổi List<LinkedHahMap>sang JSONArrayđể tạo một CSV, CSVđược tạo nhưng không theo thứ tự như của tôi List . Tôi đã cố gắng sử dụng hai lib mà bạn trình bày ở đây, nhưng tôi không thể tìm thấy phương pháp để chuyển đổi sang CSV. Bạn có thể vui lòng cho biết thêm chi tiết.
Ismail Sen

2

Tôi biết điều này đã được giải quyết và câu hỏi đã được đặt ra từ lâu, nhưng khi tôi đang giải quyết một vấn đề tương tự, tôi muốn đưa ra một cách tiếp cận hoàn toàn khác cho vấn đề này:

Đối với mảng, nó nói "Một mảng là một tập hợp các giá trị có thứ tự." tại http://www.json.org/ - nhưng các đối tượng ("Một đối tượng là một tập hợp các cặp tên / giá trị không có thứ tự.") không được sắp xếp theo thứ tự.

Tôi tự hỏi tại sao đối tượng đó lại nằm trong một mảng - điều đó ngụ ý một thứ tự không có ở đó.

{
"items":
[
    {
        "WR":"qwe",
        "QU":"asd",
        "QA":"end",
        "WO":"hasd",
        "NO":"qwer"
    },
]
}

Vì vậy, một giải pháp sẽ là đặt các khóa trong một mảng "thực" và thêm dữ liệu dưới dạng đối tượng vào mỗi khóa như sau:

{
"items":
[
    {"WR": {"data": "qwe"}},
    {"QU": {"data": "asd"}},
    {"QA": {"data": "end"}},
    {"WO": {"data": "hasd"}},
    {"NO": {"data": "qwer"}}
]
}

Vì vậy, đây là một cách tiếp cận cố gắng xem xét lại mô hình ban đầu và mục đích của nó. Nhưng tôi chưa thử nghiệm (và tôi tự hỏi) liệu tất cả các công cụ liên quan có bảo toàn thứ tự của mảng JSON gốc đó không.


1
điều này không cho phép tôi tra cứu khóa.
mickeymoon

Vậy thì bạn muốn gì - một hàm băm hay thứ gì đó được đặt hàng !? Nếu bạn muốn kết hợp cả hai, thì hãy tạo cả hai và có một trong những cấu trúc đó lập chỉ mục cho cấu trúc kia .... nếu không thì đây có vẻ là một vấn đề thiết kế nhiều hơn hoặc trộn sở thích.
cslotty

1
nó không phải là về việc trộn các sở thích, nó là một trường hợp sử dụng khá hợp lý, trong các ngôn ngữ như Java được xử lý bởi các cấu trúc như LinkedHashMap, một bản đồ có thứ tự bảo toàn thứ tự chèn. Sau đó, tôi muốn gì, tôi muốn cả hai đều có thể lặp lại các phím theo thứ tự đã xác định và tra cứu nhanh các phím đó. Tôi nghĩ câu trả lời của @Robotic Pants sẽ hoạt động khá hiệu quả, mặc dù nó hơi khó hiểu.
mickeymoon

Đúng vậy, mickeymoon, tôi đã định nói điều đó! Nhưng trong JSON, điều này không tồn tại, phải không? Sau đó, bạn sẽ phải liên quan đến ngôn ngữ / cơ chế, cung cấp cho bạn một thứ như vậy.
cslotty

1

Trong thế giới thực, một ứng dụng hầu như sẽ luôn có java bean hoặc miền sẽ được tuần tự hóa / hủy tuần tự hóa đến / từ JSON. Nó đã được đề cập rằng đặc tả đối tượng JSON không đảm bảo trật tự và bất kỳ thao tác nào đối với hành vi đó không phù hợp với yêu cầu. Tôi đã có cùng một kịch bản trong ứng dụng của mình, nơi tôi cần duy trì trật tự chỉ vì mục đích dễ đọc. Tôi đã sử dụng cách jackson tiêu chuẩn để tuần tự hóa bean java của mình thành JSON:

Object object = getObject();  //the source java bean that needs conversion
String jsonString = new com.fasterxml.jackson.databind.ObjectMapper().writeValueAsString(object);

Để tạo json với một tập hợp các phần tử có thứ tự, tôi chỉ cần sử dụng chú thích thuộc tính JSON trong Java bean mà tôi đã sử dụng để chuyển đổi. Ví dụ dưới đây:

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({"name","phone","city","id"})
public class SampleBean implements Serializable {
    private int id;
    private String name:
    private String city;
    private String phone;

    //...standard getters and setters
}

getObject () được sử dụng ở trên:

public SampleBean getObject(){
    SampleBean bean  = new SampleBean();
    bean.setId("100");
    bean.setName("SomeName");
    bean.setCity("SomeCity");
    bean.setPhone("1234567890");
    return bean;
}

Kết quả hiển thị theo chú thích thứ tự thuộc tính Json:

{
    name: "SomeName",
    phone: "1234567890",
    city: "SomeCity",
    id: 100
}

0

Cách an toàn nhất có lẽ là phương pháp ghi đè khóa được sử dụng để tạo đầu ra:

new JSONObject(){
  @Override
  public Iterator keys(){
    TreeSet<Object> sortedKeys = new TreeSet<Object>();
    Iterator keys = super.keys();
    while(keys.hasNext()){
      sortedKeys.add(keys.next());
    }
    return sortedKeys.iterator();
  }
};

1
Điều này không giải quyết được vấn đề đã nêu. Nó làm cho các khóa được sắp xếp ... nhưng câu hỏi yêu cầu thứ tự chèn được giữ nguyên.
Stephen C

0

patchFor (answer @gary):

$ git diff JSONObject.java                                                         
diff --git a/JSONObject.java b/JSONObject.java
index e28c9cd..e12b7a0 100755
--- a/JSONObject.java
+++ b/JSONObject.java
@@ -32,7 +32,7 @@ import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.Collection;
 import java.util.Enumeration;
-import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.Iterator;
 import java.util.Locale;
 import java.util.Map;
@@ -152,7 +152,9 @@ public class JSONObject {
      * Construct an empty JSONObject.
      */
     public JSONObject() {
-        this.map = new HashMap<String, Object>();
+//      this.map = new HashMap<String, Object>();
+        // I want to keep order of the given data:
+        this.map = new LinkedHashMap<String, Object>();
     }

     /**
@@ -243,7 +245,7 @@ public class JSONObject {
      * @throws JSONException
      */
     public JSONObject(Map<String, Object> map) {
-        this.map = new HashMap<String, Object>();
+        this.map = new LinkedHashMap<String, Object>();
         if (map != null) {
             Iterator<Entry<String, Object>> i = map.entrySet().iterator();
             while (i.hasNext()) {

0

Bạn có thể sử dụng mã sau để thực hiện tuần tự hóa ORDERED tùy chỉnh và deserialization của JSON Array (Ví dụ này giả sử bạn đang đặt hàng các Chuỗi nhưng có thể áp dụng cho tất cả các loại):

Serialization

JSONArray params = new JSONArray();
int paramIndex = 0;

for (String currParam : mParams)
{
    JSONObject paramObject = new JSONObject();
    paramObject.put("index", paramIndex);
    paramObject.put("value", currParam);

    params.put(paramObject);
    ++paramIndex;
}

json.put("orderedArray", params);

Hủy đăng ký

JSONArray paramsJsonArray = json.optJSONArray("orderedArray");
if (null != paramsJsonArray)
{
    ArrayList<String> paramsArr = new ArrayList<>();
    for (int i = 0; i < paramsJsonArray.length(); i++)
    {
        JSONObject param = paramsJsonArray.optJSONObject(i);
        if (null != param)
        {
            int paramIndex = param.optInt("index", -1);
            String paramValue = param.optString("value", null);

            if (paramIndex > -1 && null != paramValue)
            {
                paramsArr.add(paramIndex, paramValue);
            }
        }
    }
}

0

Ví dụ của bạn:

{
    "items":
    [
        {
            "WR":"qwe",
            "QU":"asd",
            "QA":"end",
            "WO":"hasd",
            "NO":"qwer"
        },
        ...
    ]
}

thêm một phần tử "itemorder"

{
    "items":
    [
        {
            "WR":"qwe",
            "QU":"asd",
            "QA":"end",
            "WO":"hasd",
            "NO":"qwer"
        },
        ...
    ],
    "itemorder":["WR","QU","QA","WO","NO"]
}

Mã này tạo ra kết quả mong muốn mà không có dòng tiêu đề cột:

JSONObject output = new JSONObject(json);
JSONArray docs = output.getJSONArray("data");
JSONArray names = output.getJSONArray("itemOrder");
String csv = CDL.toString(names,docs);

Điều này loại bỏ các tiêu đề của CSV, bây giờ tôi có các hàng đặt hàng nhưng không có tiêu đề
Pedro Joaquín

0

thay vì sử dụng jsonObject, hãy thử sử dụng CsvSchema theo cách của nó dễ dàng hơn và trực tiếp chuyển đổi đối tượng thành csv

CsvSchema schema = csvMapper.schemaFor(MyClass.class).withHeader();
        csvMapper.writer(schema).writeValueAsString(myClassList);

và nó đề cập đến id đơn hàng mà pojo của bạn có @JsonPropertyOrder trong đó


0

Underscore-java giữ thứ tự cho các phần tử trong khi đọc json. Tôi là người duy trì dự án.

String json = "{\n"
      + "    \"items\":\n"
      + "    [\n"
      + "        {\n"
      + "            \"WR\":\"qwe\",\n"
      + "            \"QU\":\"asd\",\n"
      + "            \"QA\":\"end\",\n"
      + "            \"WO\":\"hasd\",\n"
      + "            \"NO\":\"qwer\"\n"
      + "        }\n"
      + "    ]\n"
      + "}";
System.out.println(U.fromJson(json));

// {items=[{WR=qwe, QU=asd, QA=end, WO=hasd, NO=qwer}]}

-1

Đã thử nghiệm giải pháp nháy mắt và hoạt động tốt:

@Test
public void testJSONObject() {
    JSONObject jsonObject = new JSONObject();
    jsonObject.put("bbb", "xxx");
    jsonObject.put("ccc", "xxx");
    jsonObject.put("aaa", "xxx");
    jsonObject.put("xxx", "xxx");
    System.out.println(jsonObject.toString());
    assertTrue(jsonObject.toString().startsWith("{\"xxx\":"));
}

@Test
public void testWinkJSONObject() throws JSONException {
    org.apache.wink.json4j.JSONObject jsonObject = new OrderedJSONObject();
    jsonObject.put("bbb", "xxx");
    jsonObject.put("ccc", "xxx");
    jsonObject.put("aaa", "xxx");
    jsonObject.put("xxx", "xxx");
    assertEquals("{\"bbb\":\"xxx\",\"ccc\":\"xxx\",\"aaa\":\"xxx\",\"xxx\":\"xxx\"}", jsonObject.toString());
}

Sự phụ thuộc của Maven: <dependency> <groupId> org.apache.wink </groupId> <artifactId> wink-json4j </artifactId> <version> 1.4 </version> </dependency>
jgpelaez

Câu trả lời tương tự như @cypressious ... được đăng 2 năm trước đó. Và ví dụ không thêm giá trị thực.
Stephen C
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.