# Mass conversion of direct OPC tags to UDT's

**URL:** <https://forum.inductiveautomation.com/t/mass-conversion-of-direct-opc-tags-to-udts/66693>\
**Category:** General Discussion\
**Created:** [November 18, 2022, 4:24pm UTC](https://forum.inductiveautomation.com/t/mass-conversion-of-direct-opc-tags-to-udts/66693 "2022-11-18T16:24:35Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![tashby](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/tashby/32/67562_2.png) [@tashby](https://forum.inductiveautomation.com/u/tashby)\
**Post date:** [November 18, 2022, 4:24pm UTC](https://forum.inductiveautomation.com/t/mass-conversion-of-direct-opc-tags-to-udts/66693/1 "2022-11-18T16:24:35Z")

</div>

I have a ton of existing direct OPC tags that need to be converted to UDT's to match standards of current programming. In the end, I just need the original OPC tag path to end up as a parameter of the updated UDT.

Is there any quick way to do this? Originally, I was thinking possible with Find/Replace in a json export, but where the parameters of both span multiple lines and have different properties, I'm not sure that is possible. Would some sort of script work to browse tags and change the type?

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [November 18, 2022, 4:46pm UTC](https://forum.inductiveautomation.com/t/mass-conversion-of-direct-opc-tags-to-udts/66693/2 "2022-11-18T16:46:13Z")

</div>

`jq` is a very powerful (somewhat hard to use) tool to make structural manipulations to JSON data:  
[https://stedolan.github.io/jq/](https://stedolan.github.io/jq/)

You could likely also accomplish this through scripting, but I'd probably do it with jq, to be honest.

For example, adding a computed tooltip to all your OPC tags:

> [@How to create / append bulk tooltips via script with json export?](https://forum.inductiveautomation.com/t/how-to-create-append-bulk-tooltips-via-script-with-json-export/50072/4):
>
> You can do it with jq (a downloadable command-line executable designed to manipulate JSON): walk( if type == "object" and .valueSource == "opc" then .tooltip = "TagName: \(.name) \(.opcItemPath)" else . end) [https://jqplay.org/s/Pe6T7qNEFY](https://jqplay.org/s/Pe6T7qNEFY) I mostly copied this snippet from here:

---

<div class="post-metadata">

**Author:** ![tashby](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/tashby/32/67562_2.png) [@tashby](https://forum.inductiveautomation.com/u/tashby)\
**Post date:** [November 18, 2022, 8:36pm UTC](https://forum.inductiveautomation.com/t/mass-conversion-of-direct-opc-tags-to-udts/66693/3 "2022-11-18T20:36:54Z")

</div>

Thank you. I will look into this and see if I can work it out.

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [November 18, 2022, 9:03pm UTC](https://forum.inductiveautomation.com/t/mass-conversion-of-direct-opc-tags-to-udts/66693/4 "2022-11-18T21:03:14Z")

</div>

> [@paul-griffith](#):
>
> somewhat hard to use

You can say that again! While it's pretty cool when you finally get the statement right, I could have written something in python, welcomed the next new year, and celebrated the following Christmas in the time it takes to work it out 😄

If you're familiar with batch or powershell though it might be more logical. I struggle with these as well as I just havebt had the chance or desire to learn them properly

---

<div class="post-metadata">

**Author:** ![tashby](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/tashby/32/67562_2.png) [@tashby](https://forum.inductiveautomation.com/u/tashby)\
**Post date:** [November 18, 2022, 9:44pm UTC](https://forum.inductiveautomation.com/t/mass-conversion-of-direct-opc-tags-to-udts/66693/5 "2022-11-18T21:44:49Z")

</div>

Yeah. I'm struggling at the moment just figuring how to direct the program to the file I need to work on etc. I have stuff installed. Can't even get to where I need to come up with the syntax of replacement I need. Just trying to do a sample still.

---

<div class="post-metadata">

**Author:** ![tashby](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/tashby/32/67562_2.png) [@tashby](https://forum.inductiveautomation.com/u/tashby)\
**Post date:** [November 18, 2022, 9:49pm UTC](https://forum.inductiveautomation.com/t/mass-conversion-of-direct-opc-tags-to-udts/66693/6 "2022-11-18T21:49:29Z")

</div>

@paul-griffith I've been trying with the sample json string from your other linked forum note. Here's some snips of my setup. I'm missing like a quote or how I'm supposed to reference the file directory or something dumb I'm sure.  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/b/a/ba6781b5910d8d673aeea67c3eae8b439ff8ddac.png)

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/c/c/cc2367f550ed6af151f5940fad45b8d795f7acb7.png)

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [November 18, 2022, 9:56pm UTC](https://forum.inductiveautomation.com/t/mass-conversion-of-direct-opc-tags-to-udts/66693/7 "2022-11-18T21:56:37Z")

</div>

You probably want this one:

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/1/4/14670468b670858fa0d1402f16d137acd6b925db.png)

But wrap your jq "query" in single quotes:  
`jq.exe 'walk xxx' path_to_first_file.json > path_to_output.json`

---

<div class="post-metadata">

**Author:** ![tashby](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/tashby/32/67562_2.png) [@tashby](https://forum.inductiveautomation.com/u/tashby)\
**Post date:** [November 18, 2022, 10:04pm UTC](https://forum.inductiveautomation.com/t/mass-conversion-of-direct-opc-tags-to-udts/66693/8 "2022-11-18T22:04:08Z")

</div>

Getting closer at least. It did create file this time, however it is empty.

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/5/e/5e9a6f86ca8c3210aae32963607017977a9407dc.png)

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [November 18, 2022, 10:15pm UTC](https://forum.inductiveautomation.com/t/mass-conversion-of-direct-opc-tags-to-udts/66693/9 "2022-11-18T22:15:29Z")

</div>

![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/1/9/199011331c58fb5f8b0a46ed6fbe139a586fb7c4.png)  
Looks like some funky quotes snuck into what you're trying. Try recopying, or put it into a text editor and ensuring those are true `"` characters and there's no other funky stuff.

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [November 18, 2022, 10:15pm UTC](https://forum.inductiveautomation.com/t/mass-conversion-of-direct-opc-tags-to-udts/66693/10 "2022-11-18T22:15:37Z")

</div>

I used to use this  
[https://jqplay.org/](https://jqplay.org/)  
Depends how large your file is I guess. It's far easier to work in though

---

<div class="post-metadata">

**Author:** ![tashby](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/tashby/32/67562_2.png) [@tashby](https://forum.inductiveautomation.com/u/tashby)\
**Post date:** [November 18, 2022, 10:23pm UTC](https://forum.inductiveautomation.com/t/mass-conversion-of-direct-opc-tags-to-udts/66693/11 "2022-11-18T22:23:42Z")

</div>

Tried that link and also tried simplifying the query. Not sure what it means by expecting $end

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/a/c/acd05f625aab80a23bb6dbbcd8b7053651457ca4.png)

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [November 18, 2022, 10:31pm UTC](https://forum.inductiveautomation.com/t/mass-conversion-of-direct-opc-tags-to-udts/66693/12 "2022-11-18T22:31:44Z")

</div>

On the website, you don't need to wrap in quotes at the outer layer.

---

<div class="post-metadata">

**Author:** ![tashby](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/tashby/32/67562_2.png) [@tashby](https://forum.inductiveautomation.com/u/tashby)\
**Post date:** [November 18, 2022, 10:48pm UTC](https://forum.inductiveautomation.com/t/mass-conversion-of-direct-opc-tags-to-udts/66693/13 "2022-11-18T22:48:25Z")

</div>

Man. I feel like a child trying to work through this. Thank you for your help and patience. I go it to work on the website.

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/a/d/adbf8cff5830f4836783ae072c58d704129ac131.png)

However, when trying to apply it in command shell, it seems to think I have an unterminate 'if' statement.

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/6/9/69c28a70ae031087126ec206d0875e9852220dbc.png)

---

<div class="post-metadata">

**Author:** ![tashby](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/tashby/32/67562_2.png) [@tashby](https://forum.inductiveautomation.com/u/tashby)\
**Post date:** [November 18, 2022, 10:59pm UTC](https://forum.inductiveautomation.com/t/mass-conversion-of-direct-opc-tags-to-udts/66693/14 "2022-11-18T22:59:38Z")

</div>

If it's any help, this is my end goal with a sample piece of json export.

I've highlighted the piece of addressing that would need to be retained. If anyone wants to put together the "magic sauce" for Command Shell to make this happen, it would make my weekend. I just don't have as much time to learn a 15th programming language/software lol.

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/3/c/3ccd64ae793b3c2fddc480ffac2cb7981c8371d3.png)

---

<div class="post-metadata">

**Author:** ![tashby](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/tashby/32/67562_2.png) [@tashby](https://forum.inductiveautomation.com/u/tashby)\
**Post date:** [November 18, 2022, 11:00pm UTC](https://forum.inductiveautomation.com/t/mass-conversion-of-direct-opc-tags-to-udts/66693/15 "2022-11-18T23:00:20Z")

</div>

here's the raw json string `{ "name": "FNR", "tagType": "Folder", "tags": [{ "valueSource": "opc", "opcItemPath": "[PLC_Test]HS9999", "dataType": "Boolean", "name": "Service", "tagType": "AtomicTag", "opcServer": "Ignition OPC-UA Server" }, { "name": "Service2", "typeId": "Logix/ControlBit", "parameters": { "ParentPath": { "dataType": "String", "value": "[PLC_Test]HS9999" } }, "tagType": "UdtInstance", "tags": [{ "name": "AccessLevel", "tagType": "AtomicTag" }, { "name": "LogRequired", "tagType": "AtomicTag" }, { "name": "Output", "tagType": "AtomicTag" }, { "name": "_rev", "tagType": "AtomicTag" }] } ] }`

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [November 18, 2022, 11:14pm UTC](https://forum.inductiveautomation.com/t/mass-conversion-of-direct-opc-tags-to-udts/66693/16 "2022-11-18T23:14:10Z")

</div>

> [@tashby](#):
>
> I just don't have as much time to learn a 15th programming language/software lol.

Haha I feel you!

Oh hey, I have code in python for that already, but I'm not at my laptop... 😕 I will be in a couple hours though

---

<div class="post-metadata">

**Author:** ![tashby](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/tashby/32/67562_2.png) [@tashby](https://forum.inductiveautomation.com/u/tashby)\
**Post date:** [November 18, 2022, 11:16pm UTC](https://forum.inductiveautomation.com/t/mass-conversion-of-direct-opc-tags-to-udts/66693/17 "2022-11-18T23:16:42Z")

</div>

That would be awesome. I'm hoping to have some working solution by mid next week if possible. It's not the end of the world if you can't get to it. I know it's all out of the kindness of our hearts to help each other out and for that I'm grateful.

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [November 18, 2022, 11:18pm UTC](https://forum.inductiveautomation.com/t/mass-conversion-of-direct-opc-tags-to-udts/66693/18 "2022-11-18T23:18:37Z")

</div>

When I'm back I'll post it. I needed it whenever I created udts from a selection of standard tags because when you just do a find replace kn the json to replace the elements with parameters it makes them static not bindings. My script goes through and converts them to bindings

---

<div class="post-metadata">

**Author:** ![tashby](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/tashby/32/67562_2.png) [@tashby](https://forum.inductiveautomation.com/u/tashby)\
**Post date:** [December 1, 2022, 12:07am UTC](https://forum.inductiveautomation.com/t/mass-conversion-of-direct-opc-tags-to-udts/66693/19 "2022-12-01T00:07:44Z")

</div>

I'm sorry, I never did get to trying out your script. I had the bug to learn this jq stuff as I figured it could be useful for a lot of things and be quite elegant in it's purpose. That being said, I thought I'd share what finally worked for me. Ultimately, I learned that you can install Ubuntu on windows and seems to be a cleaner interface to use jq from than windows powershell.

```auto
jq 'walk(if type == "object" and .valueSource == "opc" and .name == "Service" then {"name": "Service","typeId": "Logix/ControlBit","parameters":{"ParentPath":{"dataType": "String","value": (.opcItemPath)},"BaseScanClass": {"dataType": "String","value": (.tagGroup)}},"tagType": "UdtInstance","tags": [{"name": "Output","tagType": "AtomicTag"},{"name": "AccessLevel","tagType": "AtomicTag"},{"name": "_rev","tagType": "AtomicTag"},{"name": "LogRequired","tagType": "AtomicTag"}]} else . end)' serviceExport.json > serviceImport.json

```

Here's a snapshot of my original test tags. I wanted to change the Service Tag (OPC) for Pump 1 to be a UDT like is show under Pump 2.  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/d/1/d13e81589e8424f937a01cec95b734cfd917670e.png)

I exported these 2 folders to a file called serviceExport.json. Then in Ubuntu, I simply just read the file to view it's contents. Mostly for comparison before and after.

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/1/e/1e0ae0d045b66c452fe23ad7cc85f2494d44ac30.png)

Then I run the query I pasted above. I've taken a screenshot to point out some of the details of what is going on.

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/e/b/eb7e69d3fcfc05b0c70555d4e0770bf0d79c789f.png)

Then I simply import my modified json.  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/6/d/6d9b0dd1915727f7f126cf1a718c6790244166fe.png)

Worked beautifully.

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [December 1, 2022, 12:22am UTC](https://forum.inductiveautomation.com/t/mass-conversion-of-direct-opc-tags-to-udts/66693/20 "2022-12-01T00:22:32Z")

</div>

Oh wow, I think I completely misread your OP and question... I thought you wanted to convert OPC tags that were changed to memory tags for testing, back to OPC tags.  
The equivalent of giving you a lamb yiros when you ordered a pizza

[Next page](https://forum.inductiveautomation.com/t/mass-conversion-of-direct-opc-tags-to-udts/66693.md?page=2)
