Подтвердить что ты не робот

JSON соответствует XML с атрибутами?

Я разрабатываю API для своего webapp.

Я думал поддерживать только ответы JSON (а не XML), потому что более оптимизирован.

Но я только что столкнулся с этим XML:

<folders>
    <folder id="123" private="0" archived="0" order="1">Shopping</folder>
</folders>

и мне было интересно, как будет соответствовать соответствующий JSON. У меня такое ощущение, что в этом случае XML будет более компактным.

Спасибо, Dan

4b9b3361

Ответ 1

Может быть:

{
  "folders": [
    { "id":123, "private":0, "archived":0, "order":1, "title":"Shopping" },
    ...
  ]
}

Поскольку между XML и JSON нет точного соответствия, вы свободны (например, должны определить), как отображаются две структуры данных. Например, в приведенном выше элементе "папка" неявна в вложенных объектах в массиве "folders".

Это можно расширить, как в:

"folders": [{"folder": { .... }]

Etc, но по-прежнему существует проблема неспособности захватить контент + атрибуты так же последовательно, как XML. В любом случае, ваш сериализатор данных → JSON | XML, вероятно, работает определенным образом (и, пожалуйста, используйте библиотеку, а не "ручную прокачку" JSON-string-munging). То есть; формат XML и JSON должен быть единообразно продиктован (каким-то образом) структурой данных для передачи.

Ответ 2

Этот подход поддерживает обратное преобразование в XML:

{
    "folders": {
        "folder":{ 
        "@": {
            "id": "123",
            "private": "0",
            "archived": "0",
            "order": "1"
            },
        "#": "Shopping"
        }
    }
}

Он работает правильно с js2xmlparser.

Ответ 3

Пример того, как YQL представляет XML и соответствующий JSON. Не нужно ничего знать о YQL, чтобы понять это, но если вам интересно, вы можете проверить консоль YQL и попробовать себя в консоли YQL

XML

<results>
    <a href="/">NBA</a>
    <a class="topnav" href="#">TEAMS</a>
    <a href="/teams/">Teams</a>
    <a href="/hawks/">Atlanta</a>

JSON

"results": {
  "a": [
    {
     "href": "/",
     "content": "NBA"
    },
    {
     "class": "topnav",
     "href": "#",
     "content": "TEAMS"
    },
    {
     "href": "/teams/",
     "content": "Teams"
    },
    {
     "href": "/hawks/",
     "content": "Atlanta"
    },

Ответ 4

Существует обозначение/соглашение JSON, называемое badgerfish, которое пытается стандартизировать (по крайней мере, собственные термины) способ сохранения большей части семантики XML низкого уровня, когда XML DOM представлен как JSON DOM (с атрибуты, конечно) (см. http://badgerfish.ning.com/).

Таким образом, вы можете легко преобразовать представление badgerfishied-json в представление XML, и вы по-прежнему работаете над структурой с вашим любимым набором инструментов XML (для меня это выражения и инструменты XPATH/QUERY).

Также легко запомнить правила синтаксиса (всего 9), например: "Атрибуты идут в свойствах, имена которых начинаются с @". Вы можете работать в badgerfishied-json в текстовом редакторе без излишней перегрузки вашей нейронной схемы. Обычно вы можете запомнить их в первый проход.

Ответ 5

Также может быть компактным в JSON, атрибут точно такой же, как значение внутри тега

отсюда:

http://www.json.org/example.html

{"widget": {
    "debug": "on",
    "window": {
        "title": "Sample Konfabulator Widget",
        "name": "main_window",
        "width": 500,
        "height": 500
    },
    "image": { 
        "src": "Images/Sun.png",
        "name": "sun1",
        "hOffset": 250,
        "vOffset": 250,
        "alignment": "center"
    }
}}  

Тот же текст, что и XML:

<widget>
    <debug>on</debug>
    <window title="Sample Konfabulator Widget">
        <name>main_window</name>
        <width>500</width>
        <height>500</height>
    </window>
    <image src="Images/Sun.png" name="sun1">
        <hOffset>250</hOffset>
        <vOffset>250</vOffset>
        <alignment>center</alignment>
    </image>
</widget>

Ответ 6

Мне кажется, что наиболее точное соответствие между XML и JSON должно представлять XML node как триплет (т.е. массив): [имя, атрибуты, значение], с именем, являющимся строкой, атрибутом объекта с именами атрибутов в качестве ключей и значений атрибутов в виде (строковых) значений и значением строки (для атомных значений) или массивом таких триплетов.

Таким образом, JSON-эквивалент

<folders>
    <folder id="123" private="0" archived="0" order="1">Shopping</folder>
</folders>

будет

[  "folders",
   {}, 
   [
      [  "folder", 
         {   "id": "123",
             "private": "0",
             "archived": "0",
             "order": "1"
         },
         "Shopping"
      ]
   ]
]

На самом деле идея этого сопоставления заключается в следующем:

1) Преобразование XML-JSON должно быть обратимым. 2) Сохранение отношения "подобия" суб-узлов

В то же время различие между узлами атрибутов и узлами значений здесь явно.

Имеет ли смысл? И оправдывает ли это сложность?

Ответ 7

редактировать

Подобный метод защищен на http://www.jsonml.org/. Они придумали термин язык разметки JSON.


Вы можете выбрать любое отображение, которое вам нравится, но если вы отображаете

<el attr="value">
  txt
</el>

в

{"el":{"attr":"value","content":"txt"}}

тогда как бы вы отобразили:

<el attr="value" content="txt1">txt2</el>

Я бы воспользовался тем, что некоторые имена аттибут запрещены.

{"el":{"attr":"value", "content":"txt1", "":["txt"]}

Или более убедительный пример:

<widget>
  <debug>on</debug>
  <window title="Sample Konfabulator Widget">
    I just put some text here
    <name>main_window</name>
    <width>500</width>
    <height>500</height>
  </window>
  <image src="Images/Sun.png" name="sun1">
    <hOffset>250<unit>mm</unit></hOffset>
    <vOffset>250</vOffset>
    <alignment>center</alignment>
  </image>
</widget>

может сопоставить с:

{"widget":{"":[
  {"debug":{"":["on"]}},
  {"window":{"title":"Sample Konfabulator Widget", "": [
    "I just put some text here",
    {"name":{"":["main window"]}},
    {"width":{"":["500"]}},
    {"height":{"":["500"]}}
  ]},
  {"image":{"src":"Images/Sun.png", "name":"sun1", "":[
    {"hOffset":{"":["250",{"unit":{"":["mm"]}}]}},
    {"vOffset":{"":["250"]}},
    {"alignment":{"":["center"]}}
  }
]}

Правила для этого преобразования однозначны:

  • элемент преобразуется в объект.
  • Ключ объекта - это имя элемента.
  • Значением объекта является сам объект, с:
    • атрибут сопоставляется со свойством объекта. (Ключ/значение)
    • содержимое объекта сопоставляется со специальным свойством.
      • Имя специального свойства - пустая строка. Это никогда не может вступать в противоречие с именем атрибута xml.
      • Значение специального свойства - это массив.
      • В массиве простой текст представляется в виде строки.
      • В массиве элементы представлены в виде объектов, как описано выше.

Для безопасного пространства существует способ однозначно упростить упомянутое отображение:

{"widget":{"":[
  {"debug":"on"},
  {"window":{"title":"Sample Konfabulator Widget", "": [
    "I just put some text here",
    {"name":"main window"},
    {"width":"500"},
    {"height":"500"}
  ]},
  {"image":{"src":"Images/Sun.png", "name":"sun1", "":[
    {"hOffset":["250",{"unit":"mm"}]},
    {"vOffset":"250"},
    {"alignment":"center"}
  }
]}
  • Если элемент не имеет атрибутов, объект-значение (содержащий специальную пустую строку, сопоставляемую с массивом) заменяется непосредственно на массив. Так что вместо:

    { "HOffset": { "": [ "250", { "единица": { "": [ "мм"]}}]}}

ты получаешь

{"hOffset":["250",{"unit":["mm"]}]}
  • Если содержимое элемента - просто текст, массив, содержащий строковое значение, заменяется непосредственно строковым значением, поэтому вы получите:

    { "HOffset": [ "250", { "единица": "мм"}]}

Таким образом, всегда будет только один способ отобразить jml (язык разметки json) обратно в xml (или html)

Ответ 8

JSON более однородна, чем XML, и не различает атрибуты обычного текста и иерархическое содержимое. Естественным представлением для вашего примера будет

[
  {"id": 123, "private": 0, "archived": 0, "order": 1, "name": "Shopping"}
]

Это еще более компактно, чем соответствующий XML.

Ответ 9

"content" используется для фактического текста, в то время как атрибуты являются его братьями и сестрами в приведенном JSON:

{ "folders":
 { "folder":
  {
   "archived":0,
   "private":0,
   "id":123,
   "content":"Shopping",
   "order":1
  }
 }
}

Сведения о реализации Java

Ответ 10

Я столкнулся с сценарием, который требует как XML, так и JSON для ввода и вывода на основе того, что было передано. Я нашел способ, который работает с атрибутами/свойствами XML и JSON. Теперь обратите внимание, как он закодирован в Java, заставляет его работать таким образом.

Мой XML-пример:

<Log>
    <datetime>05/05/2017 13:45:22</datetime>
    <sessionid>2da236d2-3852-4a09-8067-198193d2828b</sessionid>
    <message msgType="Debug">This is my message</message>
</Log>

Мой пример JSON:

{
    "datetime":"05/05/2017 13:45:22",
    "sessionid":"2da236d2-3852-4a09-8067-198193d2828b",
    "message": {
        "content":"This is a testa",
        "msgType":"Debug"
    }
}

Как я сделал это с помощью кода Log.java:

package log;

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;

@JacksonXmlRootElement(localName = "Log")
public class Log {
    @JacksonXmlProperty(localName = "datetime")
    private String datetime;
    @JacksonXmlProperty(localName = "sessionid")
    private String sessionid;
    @JacksonXmlProperty(localName = "message")
    private Message message;

    public Log() {
        this.sessionid = "0";
        this.datetime = "";
        this.message = new Message();
    }

    public String getDatetime() {
        return datetime;
    }

    public void setDatetime(String datetime) {
        this.datetime = datetime;
    }

    public String getSessionid() {
        return sessionid;
    }

    public void setSessionid(String sessionid) {
        this.sessionid = sessionid;
    }

    public Message getMessage() {
        return message;
    }

    public void setMessage(Message message) {
        this.message = message;
    }
}

Message.java. Обратите внимание на приведенный ниже @JacksonXmlText, который является ключевым:

package log;

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText;

public class Message {
    @JacksonXmlProperty(localName = "msgType", isAttribute = true)
    private String msgType;
    @JacksonXmlText
    private String content;

    public Message() {
        this.content = "";
    }

    public String getMsgType() {
        return msgType;
    }

    public void setMsgType(String msgType) {
        switch(msgType.toLowerCase())
        {
        case "test":
        case "debug":
        case "warn":
        case "error":
            break;
        default:
            msgType = "Unknown";
            break;
        }

        this.msgType = msgType;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

Абонент в LogController.java:

..
@RequestMapping(value = "/Logger", produces={"application/xml", "application/json"}, consumes={"application/xml", "application/json"})
public ResponseEntity<String> Logger(@RequestBody String logInfo, @RequestHeader("Content-Type") String contentType) {
    try 
    {
        String xml = "";
        Log logObj = null; 
        HttpHeaders responseHeaders = new HttpHeaders();
        responseHeaders.add("Content-Type", contentType);

        if (contentType.toLowerCase().contains("json"))
        {
           ObjectMapper mapper = new ObjectMapper();
           logObj = mapper.readValue(logInfo, Log.class);
           xml = mapper.writeValueAsString(logObj);
        }
        else if (contentType.toLowerCase().contains("xml"))
        {
           XmlMapper xmlMapper = new XmlMapper();
           logObj = xmlMapper.readValue(logInfo, Log.class);
           xml = xmlMapper.writeValueAsString(logObj);
        }
        else
           return new ResponseEntity<String>(HttpStatus.BAD_REQUEST);

        //TODO GWL
        //Save Log data, via Async Web Service, Data, or System 
        return new ResponseEntity<String>(xml, responseHeaders, HttpStatus.OK);
    } 
    catch( Exception ex)
    {
        ex.printStackTrace();
        return new ResponseEntity<String>(HttpStatus.BAD_REQUEST);
    }
}

Ответ 11

Если вам нравится иметь представление о различных соглашениях для преобразования XML в JSON, есть хороший обзор: http://wiki.open311.org/JSON_and_XML_Conversion/

Одна библиотека python, поддерживающая более одного соглашения, - xmljson (https://github.com/sanand0/xmljson).

Ответ 12

Вводная оговорка: в этом ответе я намеренно отступаю от первоначального вопроса и несколько расширяю сферу. Иногда, чтобы задать вопрос, стоящий за вопросом, нам нужно сначала посмотреть на картину в целом.

Как и все животные равны, все переводы из JSON в XML и из XML в JSON неравны. Не может быть математически правильных ответов на этот вопрос, и даже если они есть, они могут быть неправильными. Все ответы будут зависеть от мнения и зависят от конкретных вариантов использования.

JSON и XML поддерживают и опускают концепции, которые затрудняют совершенные, обратимые и нативные переводы.

Чтобы назвать только некоторые:

  • XML требует корневого элемента. JSON нет.

  • XML различает элементы и атрибуты. Атрибутами являются листья, элементы могут быть листьями или ветвями. Объекты JSON близки к элементам, но не имеют прямого эквивалента атрибутов.

  • У JSON есть массивы; ближайший эквивалент XML является родительским элементом, но некоторые переводы нарушаются, когда есть только один дочерний элемент.

  • У XML есть пространства имен... Чем меньше сказано о тех, тем лучше...

  • JSON должен быть компактным и легким и ближе (по моему скромному мнению) к YAML, чем к XML.

Там, где концепция существует на исходном языке, но не на целевом языке, мы должны быть изобретательны и креативны в нашем переводе. Ваши варианты использования являются ключевыми.

например

  • Должен ли результат быть как можно более родным на целевом языке? Будем ли мы моделировать это в JSON? Будем ли мы моделировать это в XML?

  • Должен ли результат быть обратимым к первоисточнику, даже за счет "нативного ощущения"?

  • Является ли компактность критерием? Это может быть в случае JSON с XML-элементом с большим количеством элементов, но не с JSON, переведенным из XML и предназначенным для обратного перевода.

Чтобы сравнить с человеческими языками: в швейцарском немецком языке мы любим наши миниатюрные: существительные обычно сокращаются до маленькой формы, где это было бы странно на английском языке; но еще более странно, у нас есть уменьшительные глаголы!

Итак, "wir machen es köchele", технически, можно перевести как "мы будем немного готовить", или "мы немного готовим", но либо на плохом, и на неправильном английском языке, и каким-то образом упустим идею.

"мы будем готовить" или "мы повеселимся" - это намного ближе к первоначальной идее. Но я подозреваю, что Антея Белл (известность перевода с Астерикса на английский) действительно поняла бы смысл; "Давайте приготовим пир…"

Вернуться к исходному вопросу. У программистов Python есть концепция pythonesque: = наиболее подходящая для основного духа python. Ответ пользователя 166390 (принятый ответ во время этого ответа) кажется мне наиболее JSONesque.

Ответ 13

Мой выбор для представления XML, чтобы убедиться, что он как-то обратим, выглядит следующим образом (на вашем примере):

    <folders>
        <folder id="123" private="0" archived="0" order="1">Shopping</folder>
    </folders>

переводится как:

    {
      "folders": [
        {
          "@id": 123,
          "@private": 0,
          "@archived": 0,
          "@order": 1,
          "$t": "Shopping"
        }
      ]
    }

Таким образом, используя @ в качестве индикатора для "атрибута" и $t качестве индикатора для "текстового содержимого", я могу вернуть строку JSON в достоверную версию исходного XML.

Хорошим Node-пакетом для выполнения этого преобразования является XML2JSON, хотя он не делает ничего особенного с атрибутами, и для получения этого вывода требуется дополнительный код.

Ответ 14

Исключая имена атрибутов, которые всегда одинаковой длины, JSON всегда будет более компактным, так как не имеет закрывающих тегов;)