cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
908
Views
0
Helpful
4
Replies

Converting from XML to JSON (YAML) via YDK

ldacol
Level 1
Level 1

Hello everyone,

 

I'm trying to convert a Juniper vendor-specific XML configuration using CodecService encode and decode API. Juniper yang models have been generated and installed however the code is failing with an error: 

Traceback (most recent call last):
  File "convert.py", line 69, in <module>
    print(yang_xml_to_json(ARGS['xml_file']))
  File "convert.py", line 58, in yang_xml_to_json
    decoded_xml_yang = CODEC.decode(XML_PROVIDER, config_xml_yang)
  File "/opt/neteng/lib/python3.6/site-packages/ydk/errors/error_handler.py", line 112, in helper
    return func(self, provider, entity, *args, **kwargs)
  File "/opt/neteng/lib/python3.6/site-packages/ydk/services/codec_service.py", line 130, in decode
    entity = self.decode(provider, payload_holder[key], subtree)
  File "/opt/neteng/lib/python3.6/site-packages/ydk/errors/error_handler.py", line 112, in helper
    return func(self, provider, entity, *args, **kwargs)
  File "/opt/neteng/lib/python3.6/site-packages/ydk/services/codec_service.py", line 130, in decode
    entity = self.decode(provider, payload_holder[key], subtree)
  File "/opt/neteng/lib/python3.6/site-packages/ydk/errors/error_handler.py", line 112, in helper
    return func(self, provider, entity, *args, **kwargs)
  File "/opt/neteng/lib/python3.6/site-packages/ydk/services/codec_service.py", line 140, in decode
    return self._decode(provider, payload_holder, subtree)
  File "/opt/neteng/lib/python3.6/site-packages/ydk/services/codec_service.py", line 158, in _decode
    entity = _payload_to_top_entity(payload, provider.encoding)
  File "/opt/neteng/lib/python3.6/site-packages/ydk/entity_utils/entity_utils.py", line 117, in _payload_to_top_entity
    raise YModelError("Could not retrieve namespace and container name")
ydk.errors.YModelError: Could not retrieve namespace and container name

 

pip freeze | grep ydk
ydk==0.8.4
ydk-models-ietf==0.1.5.post2
ydk-models-junos-18-4==18.4.post3
ydk-models-openconfig==0.1.8

Code is the following:

import argparse
import json
import yaml
import xmltodict

from ydk.providers import CodecServiceProvider
from ydk.services import CodecService


codec = CodecService()

JSON_PROVIDER = CodecServiceProvider(type='json')
XML_PROVIDER = CodecServiceProvider(type='xml')

def yang_xml_to_json (xml_file):
    with open(xml_file, "rb") as f:
        config_xml_yang = xmltodict.parse(f, xml_attribs=True)

    decoded_xml_yang = codec.decode(XML_PROVIDER, config_xml_yang)
    yang_json = code.encode(JSON_PROVIDER, decoded_xml_yang)
    return yang_json

I am using the XML output from the YDK conversion: (YAML) ->  JSON -> XML -> JSON -> (YAML)

Thanks in advance for any suggestion or input,

Luca

1 Accepted Solution

Accepted Solutions

Hi Luka

I am happy to hear that it worked for your purposes. To use the Juniper bundle in import statements I suggest you to run command 'pip list | grep ydk' and check how the bundle package is referred to. What is related to the codec operations, you do not need to have a model referral although model bundle installation is needed. The codec is smart enough to search for the bundle in the YDK installation directories. You just have to include the top level container/list into your XML/JSON string.

Yan Gorelik
YDK Solutions

View solution in original post

4 Replies 4

ygorelik
Cisco Employee
Cisco Employee

Hi Luca

I do not understand, why do you need convert XML to a dictionary, especially since the YDK does not support conversion from/to a dictionary?

    with open(xml_file, "rb") as f:
        config_xml_yang = xmltodict.parse(f, xml_attribs=True)

You need simply read XML file to a string and give it to the codec:

with open(xml_file, "rb") as f:
    config_xml = f(read)
decoded_entity = codec.decode(XML_PROVIDER, config_xml)
config_json = codec.encode(JSON_PROVIDER, decoded_entity)

Yan Gorelik

Thank you for detailed informations. This code below was solved my problem too.

 

with open(xml_file, "rb") as f:
    config_xml = f(read)
decoded_entity = codec.decode(XML_PROVIDER, config_xml)
config_json = codec.encode(JSON_PROVIDER, decoded_entity)

 

Hi Yan,

 

Thank you, this worked for the openconfig models. I am getting "ydk.errors.YModelError: No YDK bundle installed for node path 'http://yang.juniper.net/junos/conf/interfaces:interfaces'" when decoding a simple interfaces section Juniper specific. I have generated the bundle via ydg-gen  command "./generate.py --python --bundle profiles/bundles/juniper-junos_18_4_R3.json" which included all the modules under 18.4R4 and installed (see my previous notes - bundle name ydk-models-junos-18-4==18.4.post3). Is there any specific way to refer to it?

Thank you,

Luca

{
  "name": "junos-18_4",
  "version": "18.4R3",
  "core_version": "0.8.4",
  "author": "",
  "copyright": "",
  "description": "JunOS 18.4 Yang Model",
  "long_description": "JunOS 18.4 Yang Model",
  "models": {
    "description": "JunOS 18.4 Yang Model",
    "git": [
      {
        "url": "https://github.com/Juniper/yang.git",
        "commits": [
          {
            "dir": [
              "18.4/18.4R3/common",
              "18.4/18.4R3/junos/conf",
              "18.4/18.4R3/junos/conf-with-extensions"
            ]
          }
        ]
      }
    ]
  }
}
<interfaces xmlns="http://yang.juniper.net/junos/conf/interfaces">
<interface>
    <name>xe-2/0/0</name>
    <description>Test</description>
    <unit>
    <name>0</name>
    <family>
        <inet>
        <address>
            <name>1.1.1.1/30</name>
        </address>
        </inet>
    </family>
    </unit>
</interface>
</interfaces>

 

Hi Luka

I am happy to hear that it worked for your purposes. To use the Juniper bundle in import statements I suggest you to run command 'pip list | grep ydk' and check how the bundle package is referred to. What is related to the codec operations, you do not need to have a model referral although model bundle installation is needed. The codec is smart enough to search for the bundle in the YDK installation directories. You just have to include the top level container/list into your XML/JSON string.

Yan Gorelik
YDK Solutions